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
22 Ce module contient la classe ETAPE qui sert à vérifier et à exécuter
37 from N_Exception import AsException
39 from N_utils import AsType
40 from N_ASSD import ASSD
41 from N_info import message, SUPERV
44 class ETAPE(N_MCCOMPO.MCCOMPO):
47 Cette classe hérite de MCCOMPO car ETAPE est un OBJECT composite
52 # L'attribut de classe codex est utilisé pour rattacher le module de calcul éventuel (voir Build)
53 # On le met à None pour indiquer qu'il n'y a pas de module de calcul
57 def __init__(self, oper=None, reuse=None, args={}, niveau=4):
60 - definition : objet portant les attributs de définition d'une étape de type opérateur. Il
61 est initialisé par l'argument oper.
62 - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc en sortie
63 si les conditions d'exécution de l'opérateur l'autorise
64 - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé avec l'argument args.
66 self.definition = oper
70 self.parent = CONTEXT.get_current_step()
73 self.idracine = oper.label
74 self.appel = N_utils.callee_where(niveau)
81 def make_register(self):
83 Initialise les attributs jdc, id, niveau et réalise les
84 enregistrements nécessaires
87 self.jdc = self.parent.get_jdc_root()
88 self.id = self.parent.register(self)
91 self.jdc = self.parent = None
97 Cette methode a pour fonction de retirer tous les arguments egaux à None
98 de la liste des arguments. Ils sont supposés non présents et donc retirés.
100 for k in self.valeur.keys():
101 if self.valeur[k] == None:
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'opérateur. Deux cas
114 peuvent se présenter :
116 - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création
117 et le nommage du concept.
119 - le parent est défini. Dans ce cas, l'étape demande au parent la création 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, (
130 self, self.parent.g_context))
132 sd = self.get_sd_prod()
133 # On n'utilise pas self.definition.op_init car self.parent
135 if sd != None and self.reuse == None:
136 # On ne nomme le concept que dans le cas de non reutilisation
139 except AsException, e:
140 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
141 'fichier : ', self.appel[1], e)
145 l = traceback.format_exception(
146 sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])
147 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
148 'fichier : ', self.appel[1] + '\n',
156 Cette methode est un point d'entree prevu pour realiser une execution immediatement
157 apres avoir construit les mots cles et le concept produit.
158 Par defaut, elle ne fait rien. Elle doit etre surchargee dans une autre partie du programme.
162 def get_sd_prod(self):
164 Retourne le concept résultat de l'étape
166 - cas 1 : sd_prod de oper n'est pas une fonction
167 il s'agit d'une sous classe de ASSD
168 on construit le sd à partir de cette classe
170 - cas 2 : il s'agit d'une fonction
171 on l'évalue avec les mots-clés de l'étape (mc_liste)
172 on construit le sd à partir de la classe obtenue
175 if type(self.definition.sd_prod) == types.FunctionType:
176 d = self.cree_dict_valeurs(self.mc_liste)
178 sd_prod = apply(self.definition.sd_prod, (), d)
183 traceback.print_exc()
184 l = traceback.format_exception(
185 sys.exc_info()[0], sys.exc_info()[1],
187 raise AsException("impossible d affecter un type au resultat",
189 # sys.exc_info()[0],sys.exc_info()[1],)
191 sd_prod = self.definition.sd_prod
192 # on teste maintenant si la SD est réutilisée ou s'il faut la créer
193 if self.definition.reentrant != 'n' and self.reuse:
194 # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
195 # Elle sera traitee ulterieurement.
198 self.sd = sd_prod(etape=self)
199 # Si l'operateur est obligatoirement reentrant et reuse n'a pas ete specifie, c'est une erreur.
200 # On ne fait rien ici. L'erreur sera traiter par la suite.
202 if self.sd is not None and not isinstance(self.sd, ASSD):
203 raise AsException("""
204 Impossible de typer le résultat !
206 Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte,
207 soit il y a une "," à la fin d'une commande précédente.
208 Développeur : La fonction "sd_prod" retourne un type invalide.""")
211 def get_type_produit(self):
213 return self.get_type_produit_brut()
217 def get_type_produit_brut(self):
219 Retourne le type du concept résultat de l'étape
221 - cas 1 : sd_prod de oper n'est pas une fonction
222 il s'agit d'une sous classe de ASSD
223 on retourne le nom de la classe
224 - cas 2 : il s'agit d'une fonction
225 on l'évalue avec les mots-clés de l'étape (mc_liste)
226 et on retourne son résultat
228 if type(self.definition.sd_prod) == types.FunctionType:
229 d = self.cree_dict_valeurs(self.mc_liste)
230 sd_prod = apply(self.definition.sd_prod, (), d)
232 sd_prod = self.definition.sd_prod
237 Retourne l'étape à laquelle appartient self
238 Un objet de la catégorie etape doit retourner self pour indiquer que
239 l'étape a été trouvée
245 Méthode qui supprime toutes les références arrières afin que l'objet puisse
246 etre correctement détruit par le garbage collector
248 N_MCCOMPO.MCCOMPO.supprime(self)
251 for name in dir(self):
252 if name.startswith('_cache_'):
253 setattr(self, name, None)
258 # message.debug(SUPERV, "__del__ ETAPE %s <%s>", getattr(self, 'nom', 'unknown'), self)
260 # message.debug(SUPERV, " sd : %s", self.sd.nom)
263 def get_created_sd(self):
264 """Retourne la liste des sd réellement produites par l'étape.
265 Si reuse est présent, `self.sd` a été créée avant, donc n'est pas dans
267 if not self.reuse and self.sd:
273 Indique si l'étape est active (1) ou inactive (0)
277 def set_current_step(self):
279 Methode utilisee pour que l etape self se declare etape
280 courante. Utilise par les macros
282 # message.debug(SUPERV, "call etape.set_current_step", stack_id=-1)
283 cs = CONTEXT.get_current_step()
284 if self.parent != cs:
285 raise AsException("L'étape courante", cs.nom, cs,
286 "devrait etre le parent de", self.nom, self)
288 CONTEXT.unset_current_step()
289 CONTEXT.set_current_step(self)
291 def reset_current_step(self):
293 Methode utilisee par l'etape self qui remet son etape parent comme
296 cs = CONTEXT.get_current_step()
298 raise AsException("L'étape courante", cs.nom, cs,
299 "devrait etre", self.nom, self)
301 CONTEXT.unset_current_step()
302 CONTEXT.set_current_step(self.parent)
304 def issubstep(self, etape):
306 Cette methode retourne un entier indiquant si etape est une
307 sous etape de self ou non
310 Une étape simple n'a pas de sous etape
314 def get_file(self, unite=None, fic_origine='', fname=None):
316 Retourne le nom du fichier correspondant à un numero d'unité
317 logique (entier) ainsi que le source contenu dans le fichier
320 return self.jdc.get_file(unite=unite, fic_origine=fic_origine, fname=fname)
323 if os.path.exists("fort." + str(unite)):
324 fname = "fort." + str(unite)
326 raise AsException("Impossible de trouver le fichier correspondant"
327 " a l unite %s" % unite)
328 if not os.path.exists(fname):
329 raise AsException("%s n'est pas un fichier existant" % unite)
330 fproc = open(fname, 'r')
333 text = text.replace('\r\n', '\n')
334 linecache.cache[fname] = 0, 0, text.split('\n'), fname
337 def accept(self, visitor):
339 Cette methode permet de parcourir l'arborescence des objets
340 en utilisant le pattern VISITEUR
342 visitor.visitETAPE(self)
344 def update_context(self, d):
346 Cette methode doit updater le contexte fournit par
347 l'appelant en argument (d) en fonction de sa definition
349 if type(self.definition.op_init) == types.FunctionType:
350 apply(self.definition.op_init, (self, d))
352 d[self.sd.nom] = self.sd
355 """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
360 etape.state = 'modified'
365 for objet in self.mc_liste:
366 new_obj = objet.copy()
367 new_obj.reparent(etape)
368 etape.mc_liste.append(new_obj)
371 def copy_reuse(self, old_etape):
372 """ Méthode qui copie le reuse d'une autre étape.
374 if hasattr(old_etape, "reuse"):
375 self.reuse = old_etape.reuse
377 def copy_sdnom(self, old_etape):
378 """ Méthode qui copie le sdnom d'une autre étape.
380 if hasattr(old_etape, "sdnom"):
381 self.sdnom = old_etape.sdnom
383 def reparent(self, parent):
385 Cette methode sert a reinitialiser la parente de l'objet
388 self.jdc = parent.get_jdc_root()
390 for mocle in self.mc_liste:
392 if self.sd and self.reuse == None:
393 self.sd.jdc = self.jdc
395 def get_cmd(self, nomcmd):
397 Méthode pour recuperer la definition d'une commande
398 donnee par son nom dans les catalogues declares
400 Appele par un ops d'une macro en Python
402 return self.jdc.get_cmd(nomcmd)
404 def copy_intern(self, etape):
406 Méthode permettant lors du processus de recopie de copier
407 les elements internes d'une etape dans une autre
411 def full_copy(self, parent=None):
413 Méthode permettant d'effectuer une copie complète
414 d'une étape (y compris concept produit, éléments internes)
415 Si l'argument parent est fourni, la nouvelle étape
416 aura cet objet comme parent.
418 new_etape = self.copy()
419 new_etape.copy_reuse(self)
420 new_etape.copy_sdnom(self)
422 new_etape.reparent(parent)
424 new_sd = self.sd.__class__(etape=new_etape)
425 new_etape.sd = new_sd
426 if self.reuse == None:
427 new_etape.parent.NommerSdprod(new_sd, self.sd.nom)
429 new_sd.set_name(self.sd.nom)
430 new_etape.copy_intern(self)
433 def reset_jdc(self, new_jdc):
435 Reinitialise le nommage du concept de l'etape lors d'un changement de jdc
437 if self.sd and self.reuse == None:
438 self.parent.NommerSdprod(self.sd, self.sd.nom)
440 def is_include(self):
441 """Permet savoir si on a affaire à la commande INCLUDE
442 car le comportement de ces macros est particulier.
444 return self.nom.startswith('INCLUDE')
446 def sd_accessible(self):
447 """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD produite par l'étape.
450 print '`- ETAPE sd_accessible :', self.nom
451 return self.parent.sd_accessible()
453 def get_concept(self, nomsd):
455 Méthode pour recuperer un concept à partir de son nom
457 # pourrait être appelée par une commande fortran faisant appel à des fonctions python
458 # on passe la main au parent
459 return self.parent.get_concept(nomsd)