2 # Copyright (C) 2007-2021 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)
94 def makeRegister(self):
96 Initialise les attributs jdc, id, niveau et realise les
97 enregistrements necessaires
100 #print ('makeRegister de ETAPE')
102 self.jdc = self.parent.getJdcRoot()
103 self.id = self.parent.register(self)
106 self.jdc = self.parent = None
110 def nettoiargs(self):
112 Cette methode a pour fonction de retirer tous les arguments egaux a None
113 de la liste des arguments. Ils sont supposes non presents et donc retires.
115 for k in list(self.valeur.keys()):
116 if self.valeur[k] == None:
121 Demande la construction des sous-objets et les stocke dans l'attribut
124 self.mcListe = self.buildMc()
126 def buildSd(self, nom):
128 Construit le concept produit de l'operateur. Deux cas
129 peuvent se presenter :
131 - le parent n'est pas defini. Dans ce cas, l'etape prend en charge la creation
132 et le nommage du concept.
134 - le parent est defini. Dans ce cas, l'etape demande au parent la creation et
135 le nommage du concept.
141 sd = self.parent.createSdprod(self, nom)
142 if type(self.definition.op_init) == types.FunctionType:
143 self.definition.op_init(*(
144 self, self.parent.g_context))
146 sd = self.getSdProd()
147 # On n'utilise pas self.definition.op_init car self.parent
149 if sd != None and self.reuse == None:
150 # On ne nomme le concept que dans le cas de non reutilisation
153 except AsException as e:
154 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
155 'fichier : ', self.appel[1], e)
159 l = traceback.format_exception(
160 sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])
161 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
162 'fichier : ', self.appel[1] + '\n',
170 Cette methode est un point d'entree prevu pour realiser une execution immediatement
171 apres avoir construit les mots cles et le concept produit.
172 Par defaut, elle ne fait rien. Elle doit etre surchargee dans une autre partie du programme.
178 Retourne le concept resultat de l'etape
180 - cas 1 : sd_prod de oper n'est pas une fonction
181 il s'agit d'une sous classe de ASSD
182 on construit le sd a partir de cette classe
184 - cas 2 : il s'agit d'une fonction
185 on l'evalue avec les mots-cles de l'etape (mcListe)
186 on construit le sd a partir de la classe obtenue
189 if type(self.definition.sd_prod) == types.FunctionType:
190 d = self.creeDictValeurs(self.mcListe)
192 sd_prod = self.definition.sd_prod(*(), **d)
195 except Exception as exc:
197 traceback.print_exc()
198 raise AsException("impossible d affecter un type au resultat:",
201 sd_prod = self.definition.sd_prod
202 # on teste maintenant si la SD est reutilisee ou s'il faut la creer
203 if self.definition.reentrant != 'n' and self.reuse:
204 # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
205 # Elle sera traitee ulterieurement.
208 self.sd = sd_prod(etape=self)
209 # Si l'operateur est obligatoirement reentrant et reuse n'a pas ete specifie, c'est une erreur.
210 # On ne fait rien ici. L'erreur sera traiter par la suite.
212 if self.sd is not None and not isinstance(self.sd, ASSD):
213 raise AsException("""
214 Impossible de typer le resultat !
216 Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte,
217 soit il y a une "," a la fin d'une commande precedente.
218 Developpeur : La fonction "sd_prod" retourne un type invalide.""")
221 def getType_produit(self):
223 return self.getType_produit_brut()
227 def getType_produit_brut(self):
229 Retourne le type du concept resultat de l'etape
231 - cas 1 : sd_prod de oper n'est pas une fonction
232 il s'agit d'une sous classe de ASSD
233 on retourne le nom de la classe
234 - cas 2 : il s'agit d'une fonction
235 on l'evalue avec les mots-cles de l'etape (mcListe)
236 et on retourne son resultat
238 if type(self.definition.sd_prod) == types.FunctionType:
239 d = self.creeDictValeurs(self.mcListe)
240 sd_prod = self.definition.sd_prod(*(), **d)
242 sd_prod = self.definition.sd_prod
247 Retourne l'etape a laquelle appartient self
248 Un objet de la categorie etape doit retourner self pour indiquer que
249 l'etape a ete trouvee
255 Methode qui supprime toutes les references arrières afin que l'objet puisse
256 etre correctement detruit par le garbage collector
258 N_MCCOMPO.MCCOMPO.supprime(self)
261 for name in dir(self):
262 if name.startswith('_cache_'):
263 setattr(self, name, None)
270 def getCreated_sd(self):
271 """Retourne la liste des sd reellement produites par l'etape.
272 Si reuse est present, `self.sd` a ete creee avant, donc n'est pas dans
274 if not self.reuse and self.sd:
280 Indique si l'etape est active (1) ou inactive (0)
284 def setCurrentStep(self):
286 Methode utilisee pour que l etape self se declare etape
287 courante. Utilise par les macros
289 cs = CONTEXT.getCurrentStep()
290 if self.parent != cs:
291 raise AsException("L'etape courante", cs.nom, cs,
292 "devrait etre le parent de", self.nom, self)
294 CONTEXT.unsetCurrentStep()
295 CONTEXT.setCurrentStep(self)
297 def resetCurrentStep(self):
299 Methode utilisee par l'etape self qui remet son etape parent comme
302 cs = CONTEXT.getCurrentStep()
304 raise AsException("L'etape courante", cs.nom, cs,
305 "devrait etre", self.nom, self)
307 CONTEXT.unsetCurrentStep()
308 CONTEXT.setCurrentStep(self.parent)
310 def issubstep(self, etape):
312 Cette methode retourne un entier indiquant si etape est une
313 sous etape de self ou non
316 Une etape simple n'a pas de sous etape
320 def getFile(self, unite=None, fic_origine='', fname=None):
322 Retourne le nom du fichier correspondant a un numero d'unite
323 logique (entier) ainsi que le source contenu dans le fichier
326 return self.jdc.getFile(unite=unite, fic_origine=fic_origine, fname=fname)
329 if os.path.exists("fort." + str(unite)):
330 fname = "fort." + str(unite)
332 raise AsException("Impossible de trouver le fichier correspondant"
333 " a l unite %s" % unite)
334 if not os.path.exists(fname):
335 raise AsException("%s n'est pas un fichier existant" % unite)
336 fproc = open(fname, 'r')
339 text = text.replace('\r\n', '\n')
340 linecache.cache[fname] = 0, 0, text.split('\n'), fname
343 def accept(self, visitor):
345 Cette methode permet de parcourir l'arborescence des objets
346 en utilisant le pattern VISITEUR
348 visitor.visitETAPE(self)
350 def updateContext(self, d):
352 Cette methode doit updater le contexte fournit par
353 l'appelant en argument (d) en fonction de sa definition
355 if type(self.definition.op_init) == types.FunctionType:
356 self.definition.op_init(*(self, d))
358 d[self.sd.nom] = self.sd
361 """ Methode qui retourne une copie de self non enregistree auprès du JDC
366 etape.state = 'modified'
371 for objet in self.mcListe:
372 new_obj = objet.copy()
373 new_obj.reparent(etape)
374 etape.mcListe.append(new_obj)
377 def copyReuse(self, old_etape):
378 """ Methode qui copie le reuse d'une autre etape.
380 if hasattr(old_etape, "reuse"):
381 self.reuse = old_etape.reuse
383 def copySdnom(self, old_etape):
384 """ Methode qui copie le sdnom d'une autre etape.
386 if hasattr(old_etape, "sdnom"):
387 self.sdnom = old_etape.sdnom
389 def reparent(self, parent):
391 Cette methode sert a reinitialiser la parente de l'objet
394 self.jdc = parent.getJdcRoot()
396 for mocle in self.mcListe:
398 if self.sd and self.reuse == None:
399 self.sd.jdc = self.jdc
401 def getCmd(self, nomcmd):
403 Methode pour recuperer la definition d'une commande
404 donnee par son nom dans les catalogues declares
406 Appele par un ops d'une macro en Python
408 return self.jdc.getCmd(nomcmd)
410 def copyIntern(self, etape):
412 Methode permettant lors du processus de recopie de copier
413 les elements internes d'une etape dans une autre
417 def fullCopy(self, parent=None):
419 Methode permettant d'effectuer une copie complète
420 d'une etape (y compris concept produit, elements internes)
421 Si l'argument parent est fourni, la nouvelle etape
422 aura cet objet comme parent.
424 new_etape = self.copy()
425 new_etape.copyReuse(self)
426 new_etape.copySdnom(self)
428 new_etape.reparent(parent)
430 new_sd = self.sd.__class__(etape=new_etape)
431 new_etape.sd = new_sd
432 if self.reuse == None:
433 new_etape.parent.nommerSDProd(new_sd, self.sd.nom)
435 new_sd.setName(self.sd.nom)
436 new_etape.copyIntern(self)
439 def resetJdc(self, new_jdc):
441 Reinitialise le nommage du concept de l'etape lors d'un changement de jdc
443 if self.sd and self.reuse == None:
444 self.parent.nommerSDProd(self.sd, self.sd.nom)
447 """Permet savoir si on a affaire a la commande INCLUDE
448 car le comportement de ces macros est particulier.
450 return self.nom.startswith('INCLUDE')
452 def sdAccessible(self):
453 """Dit si on peut acceder aux "valeurs" (jeveux) de l'ASSD produite par l'etape.
456 print(('`- ETAPE sdAccessible :', self.nom))
457 return self.parent.sdAccessible()
459 def getConcept(self, nomsd):
461 Methode pour recuperer un concept a partir de son nom
463 # pourrait etre appelee par une commande fortran faisant appel a des fonctions python
464 # on passe la main au parent
465 return self.parent.getConcept(nomsd)