2 # Copyright (C) 2007-2017 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.
69 - objPyxbDeConstruction
71 # faut il le faire ds MC_Build ?
72 # traitement de Pyxb si Pyxb
73 self.dicoPyxbDeConstruction = args.get('dicoPyxbDeConstruction', None)
74 if self.dicoPyxbDeConstruction :
75 del args['dicoPyxbDeConstruction']
76 self.objPyxbDeConstruction=self.dicoPyxbDeConstruction['objEnPyxb']
78 self.objPyxbDeConstruction=None
79 self.definition = oper
83 self.parent = CONTEXT.getCurrentStep()
86 self.idracine = oper.label
87 self.appel = N_utils.calleeWhere(niveau)
93 print ('uuuuuuuuuuuuuuu fin init de ETAPE', self,oper)
95 def makeRegister(self):
97 Initialise les attributs jdc, id, niveau et realise les
98 enregistrements necessaires
101 print ('makeRegister de ETAPE')
103 self.jdc = self.parent.getJdcRoot()
104 self.id = self.parent.register(self)
107 self.jdc = self.parent = None
111 def nettoiargs(self):
113 Cette methode a pour fonction de retirer tous les arguments egaux a None
114 de la liste des arguments. Ils sont supposes non presents et donc retires.
116 for k in list(self.valeur.keys()):
117 if self.valeur[k] == None:
122 Demande la construction des sous-objets et les stocke dans l'attribut
125 self.mcListe = self.buildMc()
127 def buildSd(self, nom):
129 Construit le concept produit de l'operateur. Deux cas
130 peuvent se presenter :
132 - le parent n'est pas defini. Dans ce cas, l'etape prend en charge la creation
133 et le nommage du concept.
135 - le parent est defini. Dans ce cas, l'etape demande au parent la creation et
136 le nommage du concept.
142 sd = self.parent.createSdprod(self, nom)
143 if type(self.definition.op_init) == types.FunctionType:
144 self.definition.op_init(*(
145 self, self.parent.g_context))
147 sd = self.getSdProd()
148 # On n'utilise pas self.definition.op_init car self.parent
150 if sd != None and self.reuse == None:
151 # On ne nomme le concept que dans le cas de non reutilisation
154 except AsException as e:
155 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
156 'fichier : ', self.appel[1], e)
160 l = traceback.format_exception(
161 sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])
162 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
163 'fichier : ', self.appel[1] + '\n',
171 Cette methode est un point d'entree prevu pour realiser une execution immediatement
172 apres avoir construit les mots cles et le concept produit.
173 Par defaut, elle ne fait rien. Elle doit etre surchargee dans une autre partie du programme.
179 Retourne le concept resultat de l'etape
181 - cas 1 : sd_prod de oper n'est pas une fonction
182 il s'agit d'une sous classe de ASSD
183 on construit le sd a partir de cette classe
185 - cas 2 : il s'agit d'une fonction
186 on l'evalue avec les mots-cles de l'etape (mcListe)
187 on construit le sd a partir de la classe obtenue
190 if type(self.definition.sd_prod) == types.FunctionType:
191 d = self.creeDictValeurs(self.mcListe)
193 sd_prod = self.definition.sd_prod(*(), **d)
196 except Exception as exc:
198 traceback.print_exc()
199 raise AsException("impossible d affecter un type au resultat:",
202 sd_prod = self.definition.sd_prod
203 # on teste maintenant si la SD est reutilisee ou s'il faut la creer
204 if self.definition.reentrant != 'n' and self.reuse:
205 # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
206 # Elle sera traitee ulterieurement.
209 self.sd = sd_prod(etape=self)
210 # Si l'operateur est obligatoirement reentrant et reuse n'a pas ete specifie, c'est une erreur.
211 # On ne fait rien ici. L'erreur sera traiter par la suite.
213 if self.sd is not None and not isinstance(self.sd, ASSD):
214 raise AsException("""
215 Impossible de typer le resultat !
217 Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte,
218 soit il y a une "," a la fin d'une commande precedente.
219 Developpeur : La fonction "sd_prod" retourne un type invalide.""")
222 def getType_produit(self):
224 return self.getType_produit_brut()
228 def getType_produit_brut(self):
230 Retourne le type du concept resultat de l'etape
232 - cas 1 : sd_prod de oper n'est pas une fonction
233 il s'agit d'une sous classe de ASSD
234 on retourne le nom de la classe
235 - cas 2 : il s'agit d'une fonction
236 on l'evalue avec les mots-cles de l'etape (mcListe)
237 et on retourne son resultat
239 if type(self.definition.sd_prod) == types.FunctionType:
240 d = self.creeDictValeurs(self.mcListe)
241 sd_prod = self.definition.sd_prod(*(), **d)
243 sd_prod = self.definition.sd_prod
248 Retourne l'etape a laquelle appartient self
249 Un objet de la categorie etape doit retourner self pour indiquer que
250 l'etape a ete trouvee
256 Methode qui supprime toutes les references arrières afin que l'objet puisse
257 etre correctement detruit par le garbage collector
259 N_MCCOMPO.MCCOMPO.supprime(self)
262 for name in dir(self):
263 if name.startswith('_cache_'):
264 setattr(self, name, None)
271 def getCreated_sd(self):
272 """Retourne la liste des sd reellement produites par l'etape.
273 Si reuse est present, `self.sd` a ete creee avant, donc n'est pas dans
275 if not self.reuse and self.sd:
281 Indique si l'etape est active (1) ou inactive (0)
285 def setCurrentStep(self):
287 Methode utilisee pour que l etape self se declare etape
288 courante. Utilise par les macros
290 cs = CONTEXT.getCurrentStep()
291 if self.parent != cs:
292 raise AsException("L'etape courante", cs.nom, cs,
293 "devrait etre le parent de", self.nom, self)
295 CONTEXT.unsetCurrentStep()
296 CONTEXT.setCurrentStep(self)
298 def resetCurrentStep(self):
300 Methode utilisee par l'etape self qui remet son etape parent comme
303 cs = CONTEXT.getCurrentStep()
305 raise AsException("L'etape courante", cs.nom, cs,
306 "devrait etre", self.nom, self)
308 CONTEXT.unsetCurrentStep()
309 CONTEXT.setCurrentStep(self.parent)
311 def issubstep(self, etape):
313 Cette methode retourne un entier indiquant si etape est une
314 sous etape de self ou non
317 Une etape simple n'a pas de sous etape
321 def getFile(self, unite=None, fic_origine='', fname=None):
323 Retourne le nom du fichier correspondant a un numero d'unite
324 logique (entier) ainsi que le source contenu dans le fichier
327 return self.jdc.getFile(unite=unite, fic_origine=fic_origine, fname=fname)
330 if os.path.exists("fort." + str(unite)):
331 fname = "fort." + str(unite)
333 raise AsException("Impossible de trouver le fichier correspondant"
334 " a l unite %s" % unite)
335 if not os.path.exists(fname):
336 raise AsException("%s n'est pas un fichier existant" % unite)
337 fproc = open(fname, 'r')
340 text = text.replace('\r\n', '\n')
341 linecache.cache[fname] = 0, 0, text.split('\n'), fname
344 def accept(self, visitor):
346 Cette methode permet de parcourir l'arborescence des objets
347 en utilisant le pattern VISITEUR
349 visitor.visitETAPE(self)
351 def updateContext(self, d):
353 Cette methode doit updater le contexte fournit par
354 l'appelant en argument (d) en fonction de sa definition
356 if type(self.definition.op_init) == types.FunctionType:
357 self.definition.op_init(*(self, d))
359 d[self.sd.nom] = self.sd
362 """ Methode qui retourne une copie de self non enregistree auprès du JDC
367 etape.state = 'modified'
372 for objet in self.mcListe:
373 new_obj = objet.copy()
374 new_obj.reparent(etape)
375 etape.mcListe.append(new_obj)
378 def copyReuse(self, old_etape):
379 """ Methode qui copie le reuse d'une autre etape.
381 if hasattr(old_etape, "reuse"):
382 self.reuse = old_etape.reuse
384 def copySdnom(self, old_etape):
385 """ Methode qui copie le sdnom d'une autre etape.
387 if hasattr(old_etape, "sdnom"):
388 self.sdnom = old_etape.sdnom
390 def reparent(self, parent):
392 Cette methode sert a reinitialiser la parente de l'objet
395 self.jdc = parent.getJdcRoot()
397 for mocle in self.mcListe:
399 if self.sd and self.reuse == None:
400 self.sd.jdc = self.jdc
402 def getCmd(self, nomcmd):
404 Methode pour recuperer la definition d'une commande
405 donnee par son nom dans les catalogues declares
407 Appele par un ops d'une macro en Python
409 return self.jdc.getCmd(nomcmd)
411 def copyIntern(self, etape):
413 Methode permettant lors du processus de recopie de copier
414 les elements internes d'une etape dans une autre
418 def fullCopy(self, parent=None):
420 Methode permettant d'effectuer une copie complète
421 d'une etape (y compris concept produit, elements internes)
422 Si l'argument parent est fourni, la nouvelle etape
423 aura cet objet comme parent.
425 new_etape = self.copy()
426 new_etape.copyReuse(self)
427 new_etape.copySdnom(self)
429 new_etape.reparent(parent)
431 new_sd = self.sd.__class__(etape=new_etape)
432 new_etape.sd = new_sd
433 if self.reuse == None:
434 new_etape.parent.NommerSdprod(new_sd, self.sd.nom)
436 new_sd.setName(self.sd.nom)
437 new_etape.copyIntern(self)
440 def resetJdc(self, new_jdc):
442 Reinitialise le nommage du concept de l'etape lors d'un changement de jdc
444 if self.sd and self.reuse == None:
445 self.parent.NommerSdprod(self.sd, self.sd.nom)
448 """Permet savoir si on a affaire a la commande INCLUDE
449 car le comportement de ces macros est particulier.
451 return self.nom.startswith('INCLUDE')
453 def sdAccessible(self):
454 """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD produite par l'etape.
457 print(('`- ETAPE sdAccessible :', self.nom))
458 return self.parent.sdAccessible()
460 def getConcept(self, nomsd):
462 Methode pour recuperer un concept a partir de son nom
464 # pourrait etre appelee par une commande fortran faisant appel a des fonctions python
465 # on passe la main au parent
466 return self.parent.getConcept(nomsd)