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 a verifier et a executer
27 from __future__ import absolute_import
28 from __future__ import print_function
30 from builtins import str
41 from . import N_MCCOMPO
42 from .N_Exception import AsException
44 from .N_utils import AsType
45 from .N_ASSD import ASSD
48 class ETAPE(N_MCCOMPO.MCCOMPO):
51 Cette classe herite de MCCOMPO car ETAPE est un OBJECT composite
56 # L'attribut de classe codex est utilise pour rattacher le module de calcul eventuel (voir Build)
57 # On le met a None pour indiquer qu'il n'y a pas de module de calcul
61 def __init__(self, oper=None, reuse=None, args={}, niveau=4):
64 - definition : objet portant les attributs de definition d'une etape de type operateur. Il
65 est initialise par l'argument oper.
66 - reuse : indique le concept d'entree reutilise. Il se trouvera donc en sortie
67 si les conditions d'execution de l'operateur l'autorise
68 - valeur : arguments d'entree de type mot-cle=valeur. Initialise avec l'argument args.
70 self.definition = oper
74 self.parent = CONTEXT.get_current_step()
77 self.idracine = oper.label
78 self.appel = N_utils.callee_where(niveau)
85 def make_register(self):
87 Initialise les attributs jdc, id, niveau et realise les
88 enregistrements necessaires
91 self.jdc = self.parent.get_jdc_root()
92 self.id = self.parent.register(self)
95 self.jdc = self.parent = None
101 Cette methode a pour fonction de retirer tous les arguments egaux a None
102 de la liste des arguments. Ils sont supposes non presents et donc retires.
104 for k in list(self.valeur.keys()):
105 if self.valeur[k] == None:
110 Demande la construction des sous-objets et les stocke dans l'attribut
113 self.mc_liste = self.build_mc()
115 def Build_sd(self, nom):
117 Construit le concept produit de l'operateur. Deux cas
118 peuvent se presenter :
120 - le parent n'est pas defini. Dans ce cas, l'etape prend en charge la creation
121 et le nommage du concept.
123 - le parent est defini. Dans ce cas, l'etape demande au parent la creation et
124 le nommage du concept.
130 sd = self.parent.create_sdprod(self, nom)
131 if type(self.definition.op_init) == types.FunctionType:
132 self.definition.op_init(*(
133 self, self.parent.g_context))
135 sd = self.get_sd_prod()
136 # On n'utilise pas self.definition.op_init car self.parent
138 if sd != None and self.reuse == None:
139 # On ne nomme le concept que dans le cas de non reutilisation
142 except AsException as e:
143 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
144 'fichier : ', self.appel[1], e)
148 l = traceback.format_exception(
149 sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])
150 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
151 'fichier : ', self.appel[1] + '\n',
159 Cette methode est un point d'entree prevu pour realiser une execution immediatement
160 apres avoir construit les mots cles et le concept produit.
161 Par defaut, elle ne fait rien. Elle doit etre surchargee dans une autre partie du programme.
165 def get_sd_prod(self):
167 Retourne le concept resultat de l'etape
169 - cas 1 : sd_prod de oper n'est pas une fonction
170 il s'agit d'une sous classe de ASSD
171 on construit le sd a partir de cette classe
173 - cas 2 : il s'agit d'une fonction
174 on l'evalue avec les mots-cles de l'etape (mc_liste)
175 on construit le sd a partir de la classe obtenue
178 if type(self.definition.sd_prod) == types.FunctionType:
179 d = self.cree_dict_valeurs(self.mc_liste)
181 sd_prod = self.definition.sd_prod(*(), **d)
184 except Exception as exc:
186 traceback.print_exc()
187 raise AsException("impossible d affecter un type au resultat:",
190 sd_prod = self.definition.sd_prod
191 # on teste maintenant si la SD est reutilisee ou s'il faut la creer
192 if self.definition.reentrant != 'n' and self.reuse:
193 # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
194 # Elle sera traitee ulterieurement.
197 self.sd = sd_prod(etape=self)
198 # Si l'operateur est obligatoirement reentrant et reuse n'a pas ete specifie, c'est une erreur.
199 # On ne fait rien ici. L'erreur sera traiter par la suite.
201 if self.sd is not None and not isinstance(self.sd, ASSD):
202 raise AsException("""
203 Impossible de typer le resultat !
205 Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte,
206 soit il y a une "," a la fin d'une commande precedente.
207 Developpeur : La fonction "sd_prod" retourne un type invalide.""")
210 def get_type_produit(self):
212 return self.get_type_produit_brut()
216 def get_type_produit_brut(self):
218 Retourne le type du concept resultat de l'etape
220 - cas 1 : sd_prod de oper n'est pas une fonction
221 il s'agit d'une sous classe de ASSD
222 on retourne le nom de la classe
223 - cas 2 : il s'agit d'une fonction
224 on l'evalue avec les mots-cles de l'etape (mc_liste)
225 et on retourne son resultat
227 if type(self.definition.sd_prod) == types.FunctionType:
228 d = self.cree_dict_valeurs(self.mc_liste)
229 sd_prod = self.definition.sd_prod(*(), **d)
231 sd_prod = self.definition.sd_prod
236 Retourne l'etape a laquelle appartient self
237 Un objet de la categorie etape doit retourner self pour indiquer que
238 l'etape a ete trouvee
244 Methode qui supprime toutes les references arrières afin que l'objet puisse
245 etre correctement detruit par le garbage collector
247 N_MCCOMPO.MCCOMPO.supprime(self)
250 for name in dir(self):
251 if name.startswith('_cache_'):
252 setattr(self, name, None)
259 def get_created_sd(self):
260 """Retourne la liste des sd reellement produites par l'etape.
261 Si reuse est present, `self.sd` a ete creee avant, donc n'est pas dans
263 if not self.reuse and self.sd:
269 Indique si l'etape est active (1) ou inactive (0)
273 def set_current_step(self):
275 Methode utilisee pour que l etape self se declare etape
276 courante. Utilise par les macros
278 cs = CONTEXT.get_current_step()
279 if self.parent != cs:
280 raise AsException("L'etape courante", cs.nom, cs,
281 "devrait etre le parent de", self.nom, self)
283 CONTEXT.unset_current_step()
284 CONTEXT.set_current_step(self)
286 def reset_current_step(self):
288 Methode utilisee par l'etape self qui remet son etape parent comme
291 cs = CONTEXT.get_current_step()
293 raise AsException("L'etape courante", cs.nom, cs,
294 "devrait etre", self.nom, self)
296 CONTEXT.unset_current_step()
297 CONTEXT.set_current_step(self.parent)
299 def issubstep(self, etape):
301 Cette methode retourne un entier indiquant si etape est une
302 sous etape de self ou non
305 Une etape simple n'a pas de sous etape
309 def get_file(self, unite=None, fic_origine='', fname=None):
311 Retourne le nom du fichier correspondant a un numero d'unite
312 logique (entier) ainsi que le source contenu dans le fichier
315 return self.jdc.get_file(unite=unite, fic_origine=fic_origine, fname=fname)
318 if os.path.exists("fort." + str(unite)):
319 fname = "fort." + str(unite)
321 raise AsException("Impossible de trouver le fichier correspondant"
322 " a l unite %s" % unite)
323 if not os.path.exists(fname):
324 raise AsException("%s n'est pas un fichier existant" % unite)
325 fproc = open(fname, 'r')
328 text = text.replace('\r\n', '\n')
329 linecache.cache[fname] = 0, 0, text.split('\n'), fname
332 def accept(self, visitor):
334 Cette methode permet de parcourir l'arborescence des objets
335 en utilisant le pattern VISITEUR
337 visitor.visitETAPE(self)
339 def update_context(self, d):
341 Cette methode doit updater le contexte fournit par
342 l'appelant en argument (d) en fonction de sa definition
344 if type(self.definition.op_init) == types.FunctionType:
345 self.definition.op_init(*(self, d))
347 d[self.sd.nom] = self.sd
350 """ Methode qui retourne une copie de self non enregistree auprès du JDC
355 etape.state = 'modified'
360 for objet in self.mc_liste:
361 new_obj = objet.copy()
362 new_obj.reparent(etape)
363 etape.mc_liste.append(new_obj)
366 def copy_reuse(self, old_etape):
367 """ Methode qui copie le reuse d'une autre etape.
369 if hasattr(old_etape, "reuse"):
370 self.reuse = old_etape.reuse
372 def copy_sdnom(self, old_etape):
373 """ Methode qui copie le sdnom d'une autre etape.
375 if hasattr(old_etape, "sdnom"):
376 self.sdnom = old_etape.sdnom
378 def reparent(self, parent):
380 Cette methode sert a reinitialiser la parente de l'objet
383 self.jdc = parent.get_jdc_root()
385 for mocle in self.mc_liste:
387 if self.sd and self.reuse == None:
388 self.sd.jdc = self.jdc
390 def get_cmd(self, nomcmd):
392 Methode pour recuperer la definition d'une commande
393 donnee par son nom dans les catalogues declares
395 Appele par un ops d'une macro en Python
397 return self.jdc.get_cmd(nomcmd)
399 def copy_intern(self, etape):
401 Methode permettant lors du processus de recopie de copier
402 les elements internes d'une etape dans une autre
406 def full_copy(self, parent=None):
408 Methode permettant d'effectuer une copie complète
409 d'une etape (y compris concept produit, elements internes)
410 Si l'argument parent est fourni, la nouvelle etape
411 aura cet objet comme parent.
413 new_etape = self.copy()
414 new_etape.copy_reuse(self)
415 new_etape.copy_sdnom(self)
417 new_etape.reparent(parent)
419 new_sd = self.sd.__class__(etape=new_etape)
420 new_etape.sd = new_sd
421 if self.reuse == None:
422 new_etape.parent.NommerSdprod(new_sd, self.sd.nom)
424 new_sd.set_name(self.sd.nom)
425 new_etape.copy_intern(self)
428 def reset_jdc(self, new_jdc):
430 Reinitialise le nommage du concept de l'etape lors d'un changement de jdc
432 if self.sd and self.reuse == None:
433 self.parent.NommerSdprod(self.sd, self.sd.nom)
435 def is_include(self):
436 """Permet savoir si on a affaire a la commande INCLUDE
437 car le comportement de ces macros est particulier.
439 return self.nom.startswith('INCLUDE')
441 def sd_accessible(self):
442 """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD produite par l'etape.
445 print(('`- ETAPE sd_accessible :', self.nom))
446 return self.parent.sd_accessible()
448 def get_concept(self, nomsd):
450 Methode pour recuperer un concept a partir de son nom
452 # pourrait etre appelee par une commande fortran faisant appel a des fonctions python
453 # on passe la main au parent
454 return self.parent.get_concept(nomsd)