1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2013 EDF R&D
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 Ce module contient la classe ETAPE qui sert à vérifier et à exécuter
26 import types,sys,string,os
33 from N_Exception import AsException
35 from N_utils import AsType
36 from N_ASSD import ASSD
37 from N_info import message, SUPERV
39 class ETAPE(N_MCCOMPO.MCCOMPO):
41 Cette classe hérite de MCCOMPO car ETAPE est un OBJECT composite
46 # L'attribut de classe codex est utilisé pour rattacher le module de calcul éventuel (voir Build)
47 # On le met à None pour indiquer qu'il n'y a pas de module de calcul rattaché
50 def __init__(self, oper=None, reuse=None, args={}, niveau=4):
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 - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc en sortie
56 si les conditions d'exécution de l'opérateur l'autorise
57 - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé avec l'argument args.
59 self.definition = oper
63 self.parent = CONTEXT.get_current_step()
66 self.idracine = oper.label
67 self.appel = N_utils.callee_where(niveau)
74 def make_register(self):
76 Initialise les attributs jdc, id, niveau et réalise les
77 enregistrements nécessaires
80 self.jdc = self.parent.get_jdc_root()
81 self.id = self.parent.register(self)
84 self.jdc = self.parent = None
90 Cette methode a pour fonction de retirer tous les arguments egaux à None
91 de la liste des arguments. Ils sont supposés non présents et donc retirés.
93 for k in self.valeur.keys():
94 if self.valeur[k] == None:del self.valeur[k]
98 Demande la construction des sous-objets et les stocke dans l'attribut
101 self.mc_liste=self.build_mc()
103 def Build_sd(self,nom):
105 Construit le concept produit de l'opérateur. Deux cas
106 peuvent se présenter :
108 - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création
109 et le nommage du concept.
111 - le parent est défini. Dans ce cas, l'étape demande au parent la création et
112 le nommage du concept.
115 #message.debug(SUPERV, "Build_sd %s", self.nom)
119 sd= self.parent.create_sdprod(self,nom)
120 if type(self.definition.op_init) == types.FunctionType:
121 apply(self.definition.op_init,(self,self.parent.g_context))
123 sd=self.get_sd_prod()
124 # On n'utilise pas self.definition.op_init car self.parent
126 if sd != None and self.reuse == None:
127 # On ne nomme le concept que dans le cas de non reutilisation
130 except AsException,e:
131 raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
132 'fichier : ',self.appel[1],e)
136 l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
137 raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
138 'fichier : ',self.appel[1]+'\n',
146 Cette methode est un point d'entree prevu pour realiser une execution immediatement
147 apres avoir construit les mots cles et le concept produit.
148 Par defaut, elle ne fait rien. Elle doit etre surchargee dans une autre partie du programme.
152 def get_sd_prod(self):
154 Retourne le concept résultat de l'étape
156 - cas 1 : sd_prod de oper n'est pas une fonction
157 il s'agit d'une sous classe de ASSD
158 on construit le sd à partir de cette classe
160 - cas 2 : il s'agit d'une fonction
161 on l'évalue avec les mots-clés de l'étape (mc_liste)
162 on construit le sd à partir de la classe obtenue
165 if type(self.definition.sd_prod) == types.FunctionType:
166 d=self.cree_dict_valeurs(self.mc_liste)
168 sd_prod= apply(self.definition.sd_prod,(),d)
172 if CONTEXT.debug: traceback.print_exc()
173 l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
175 raise AsException("impossible d affecter un type au resultat",
177 # sys.exc_info()[0],sys.exc_info()[1],)
179 sd_prod=self.definition.sd_prod
180 # on teste maintenant si la SD est réutilisée ou s'il faut la créer
181 if self.definition.reentrant != 'n' and self.reuse:
182 # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
183 # Elle sera traitee ulterieurement.
186 self.sd= sd_prod(etape=self)
187 # Si l'operateur est obligatoirement reentrant et reuse n'a pas ete specifie, c'est une erreur.
188 # On ne fait rien ici. L'erreur sera traiter par la suite.
190 if self.sd is not None and not isinstance(self.sd, ASSD):
191 raise AsException("""
192 Impossible de typer le résultat !
194 Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte,
195 soit il y a une "," à la fin d'une commande précédente.
196 Développeur : La fonction "sd_prod" retourne un type invalide.""")
199 def get_type_produit(self):
201 return self.get_type_produit_brut()
205 def get_type_produit_brut(self):
207 Retourne le type du concept résultat de l'étape
209 - cas 1 : sd_prod de oper n'est pas une fonction
210 il s'agit d'une sous classe de ASSD
211 on retourne le nom de la classe
212 - cas 2 : il s'agit d'une fonction
213 on l'évalue avec les mots-clés de l'étape (mc_liste)
214 et on retourne son résultat
216 if type(self.definition.sd_prod) == types.FunctionType:
217 d=self.cree_dict_valeurs(self.mc_liste)
218 sd_prod= apply(self.definition.sd_prod,(),d)
220 sd_prod=self.definition.sd_prod
225 Retourne l'étape à laquelle appartient self
226 Un objet de la catégorie etape doit retourner self pour indiquer que
227 l'étape a été trouvée
233 Méthode qui supprime toutes les références arrières afin que l'objet puisse
234 etre correctement détruit par le garbage collector
236 N_MCCOMPO.MCCOMPO.supprime(self)
239 for name in dir(self):
240 if name.startswith( '_cache_' ):
241 setattr(self, name, None)
246 #message.debug(SUPERV, "__del__ ETAPE %s <%s>", getattr(self, 'nom', 'unknown'), self)
248 #message.debug(SUPERV, " sd : %s", self.sd.nom)
251 def get_created_sd(self):
252 """Retourne la liste des sd réellement produites par l'étape.
253 Si reuse est présent, `self.sd` a été créée avant, donc n'est pas dans
255 if not self.reuse and self.sd:
261 Indique si l'étape est active (1) ou inactive (0)
265 def set_current_step(self):
267 Methode utilisee pour que l etape self se declare etape
268 courante. Utilise par les macros
270 #message.debug(SUPERV, "call etape.set_current_step", stack_id=-1)
271 cs= CONTEXT.get_current_step()
272 if self.parent != cs :
273 raise AsException("L'étape courante", cs.nom, cs,
274 "devrait etre le parent de", self.nom, self)
276 CONTEXT.unset_current_step()
277 CONTEXT.set_current_step(self)
279 def reset_current_step(self):
281 Methode utilisee par l'etape self qui remet son etape parent comme
284 cs= CONTEXT.get_current_step()
286 raise AsException("L'étape courante", cs.nom, cs,
287 "devrait etre", self.nom, self)
289 CONTEXT.unset_current_step()
290 CONTEXT.set_current_step(self.parent)
292 def issubstep(self,etape):
294 Cette methode retourne un entier indiquant si etape est une
295 sous etape de self ou non
298 Une étape simple n'a pas de sous etape
302 def get_file(self, unite=None, fic_origine='', fname=None):
304 Retourne le nom du fichier correspondant à un numero d'unité
305 logique (entier) ainsi que le source contenu dans le fichier
308 return self.jdc.get_file(unite=unite, fic_origine=fic_origine, fname=fname)
311 if os.path.exists("fort."+str(unite)):
312 fname= "fort."+str(unite)
314 raise AsException("Impossible de trouver le fichier correspondant"
315 " a l unite %s" % unite)
316 if not os.path.exists(fname):
317 raise AsException("%s n'est pas un fichier existant" % unite)
318 fproc = open(fname, 'r')
321 text = text.replace('\r\n', '\n')
322 linecache.cache[fname] = 0, 0, text.split('\n'), fname
325 def accept(self,visitor):
327 Cette methode permet de parcourir l'arborescence des objets
328 en utilisant le pattern VISITEUR
330 visitor.visitETAPE(self)
332 def update_context(self,d):
334 Cette methode doit updater le contexte fournit par
335 l'appelant en argument (d) en fonction de sa definition
337 if type(self.definition.op_init) == types.FunctionType:
338 apply(self.definition.op_init,(self,d))
340 d[self.sd.nom]=self.sd
343 """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
348 etape.state = 'modified'
353 for objet in self.mc_liste:
354 new_obj = objet.copy()
355 new_obj.reparent(etape)
356 etape.mc_liste.append(new_obj)
359 def copy_reuse(self,old_etape):
360 """ Méthode qui copie le reuse d'une autre étape.
362 if hasattr(old_etape,"reuse") :
363 self.reuse = old_etape.reuse
365 def copy_sdnom(self,old_etape):
366 """ Méthode qui copie le sdnom d'une autre étape.
368 if hasattr(old_etape,"sdnom") :
369 self.sdnom = old_etape.sdnom
371 def reparent(self,parent):
373 Cette methode sert a reinitialiser la parente de l'objet
376 self.jdc=parent.get_jdc_root()
378 for mocle in self.mc_liste:
380 if self.sd and self.reuse == None :
383 def get_cmd(self,nomcmd):
385 Méthode pour recuperer la definition d'une commande
386 donnee par son nom dans les catalogues declares
388 Appele par un ops d'une macro en Python
390 return self.jdc.get_cmd(nomcmd)
392 def copy_intern(self,etape):
394 Méthode permettant lors du processus de recopie de copier
395 les elements internes d'une etape dans une autre
399 def full_copy(self,parent=None):
401 Méthode permettant d'effectuer une copie complète
402 d'une étape (y compris concept produit, éléments internes)
403 Si l'argument parent est fourni, la nouvelle étape
404 aura cet objet comme parent.
406 new_etape = self.copy()
407 new_etape.copy_reuse(self)
408 new_etape.copy_sdnom(self)
409 if parent: new_etape.reparent(parent)
411 new_sd = self.sd.__class__(etape=new_etape)
412 new_etape.sd = new_sd
413 if self.reuse == None :
414 new_etape.parent.NommerSdprod(new_sd,self.sd.nom)
416 new_sd.set_name(self.sd.nom)
417 new_etape.copy_intern(self)
420 def reset_jdc(self,new_jdc):
422 Reinitialise le nommage du concept de l'etape lors d'un changement de jdc
424 if self.sd and self.reuse == None :
425 self.parent.NommerSdprod(self.sd,self.sd.nom)
427 def is_include(self):
428 """Permet savoir si on a affaire à la commande INCLUDE
429 car le comportement de ces macros est particulier.
431 return self.nom.startswith('INCLUDE')
433 def sd_accessible(self):
434 """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD produite par l'étape.
436 if CONTEXT.debug: print '`- ETAPE sd_accessible :', self.nom
437 return self.parent.sd_accessible()
439 def get_concept(self, nomsd):
441 Méthode pour recuperer un concept à partir de son nom
443 # pourrait être appelée par une commande fortran faisant appel à des fonctions python
444 # on passe la main au parent
445 return self.parent.get_concept(nomsd)