1 # -*- coding: utf-8 -*-
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
23 from __future__ import absolute_import
24 from __future__ import print_function
29 from Extensions.i18n import tr
30 from Extensions.eficas_exception import EficasException
32 # Objet re pour controler les identificateurs Python
33 conceptRE=re.compile(r'[a-zA-Z_]\w*$')
35 # import rajoute suite a l'ajout de buildSd --> a resorber
38 from Noyau import N_Exception
39 from Noyau.N_Exception import AsException
41 # fin import a resorber
44 from . import I_MCCOMPO
45 from . import CONNECTOR
46 from Extensions import commande_comm
48 class ETAPE(I_MCCOMPO.MCCOMPO):
54 #print "SDNAME ",self.reuse,self.sd,self.sd.getName()
56 print(("SDNAME ", self.reuse, self.sd, self.sd.getName()))
58 if self.reuse != None:
59 sdname= self.reuse.getName()
61 if self.sd:sdname=self.sd.getName()
62 if sdname.find('sansnom') != -1 or sdname.find('SD_') != -1:
63 # dans le cas ou la SD est 'sansnom' ou 'SD_' on retourne la chaine vide
67 def isReentrant(self):
69 Indique si la commande est reentrante
71 return self.definition.reentrant == 'o'
75 Met l'etat de l'etape a : modifie
76 Propage la modification au parent
78 # initModif doit etre appele avant de realiser une modification
79 # La validite devra etre recalculee apres cette modification
80 # mais dans l'appel a finModif pour preserver l'etat modified
81 # de tous les objets entre temps
82 #print "initModif",self,self.parent
83 self.state = 'modified'
85 self.parent.initModif()
89 Methode appelee une fois qu'une modification a ete faite afin de
90 declencher d'eventuels traitements post-modification
91 ex : INCLUDE et POURSUITE
92 Ne pas mettre de traitement qui risque d'induire des recursions (soit a peu pres rien)
94 CONNECTOR.Emit(self,"valid")
96 self.parent.finModif()
98 def nommeSd(self,nom) :
100 Cette methode a pour fonction de donner un nom (nom) au concept
101 produit par l'etape (self).
102 - si le concept n'existe pas, on essaye de le creer a condition que l'etape soit valide ET non reentrante)
103 - si il existe dea, on le renomme et on repercute les changements dans les autres etapes
104 Les valeurs de retour sont :
105 - 0 si le nommage n'a pas pu etre menea son terme,
106 - 1 dans le cas contraire
108 # Le nom d'un concept doit etre un identificateur Python (toujours vrai ou insuffisant?)
109 if not conceptRE.match(nom):
110 return 0, tr("Un nom de concept doit etre un identificateur Python")
112 # pour eviter que le nom du concept soit le nom de la classe --> souci pour utiliser le concept
113 if (nom == self.definition.nom) : return (0, tr("un concept de type ")+ nom + tr(" ne peut pas se nommer ") + nom)
114 if ( nom in dir(self.jdc.cata)) : return (0, nom + tr("est un not reserve"))
115 #if (not isinstance(nom,str)) : return (0, tr("Le nom ") + nom + tr(" est un mot reserve"))
116 #if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
117 # return 0, tr("Nom de concept trop long (maxi 8 caracteres)")
121 # On verifie d'abord si les mots cles sont valides
123 if not self.isValid(sd='non') : return 0,"Nommage du concept refuse : l'operateur n'est pas valide"
125 # Cas particulier des operateurs obligatoirement reentrants
126 # plus de concept reentrant (pour Aster)
128 if self.definition.reentrant == 'o':
129 self.sd = self.reuse = self.jdc.getSdAvantEtape(nom,self)
131 self.sdnom=self.sd.nom
133 return 1, tr("Concept existant")
135 return 0, tr("Operateur reentrant mais concept non existant")
137 # Cas particulier des operateurs facultativement reentrants
140 if self.definition.reentrant == 'f' :
141 sd = self.jdc.getSdAvantEtape(nom,self)
143 if isinstance(sd,self.getType_produit()) :
144 self.sd = self.reuse = sd
147 return 1, tr("Operateur reentrant et concept existant trouve")
149 return 0, tr("Concept deja existant et de mauvais type")
151 # il faut enlever le lien vers une SD existante car si on passe ici
152 # cela signifie que l'operateur n'est pas utilise en mode reentrant.
153 # Si on ne fait pas cela, on risque de modifier une SD produite par un autre operateur
156 self.sd = self.reuse = self.sdnom = None
158 # On est dans le cas ou l'operateur n'est pas reentrant ou est facultativement reentrant
159 # mais est utilise en mode non reentrant
162 #Pas de concept produit preexistant
163 if self.parent.getSdAutourEtape(nom,self):
164 # Un concept de ce nom existe dans le voisinage de l'etape courante
165 # On retablit l'ancien concept reentrant s'il existait
167 self.sd=self.reuse=old_reuse
168 self.sdnom=old_reuse.nom
169 return 0, tr("Nommage du concept refuse : un concept de meme nom existe deja")
171 # Il n'existe pas de concept de ce nom dans le voisinage de l'etape courante
172 # On peut donc creer le concept retourne
173 # Il est cree sans nom mais enregistre dans la liste des concepts existants
176 # Renommage du concept : Il suffit de changer son attribut nom pour le nommer
179 self.parent.sdsDict[nom]=self.sd
180 self.parent.updateConceptAfterEtape(self,self.sd)
182 return 1, tr("Nommage du concept effectue")
184 return 0, tr("Nommage impossible %s", str(sys.exc_info()[1]))
186 #Un concept produit preexiste
188 if old_nom.find('sansnom') :
189 # Dans le cas ou old_nom == sansnom, isValid retourne 0 alors que ...
190 # par contre si le concept existe et qu'il s'appelle sansnom c'est que l'etape est valide
191 # on peut donc le nommer sans test prealable
192 if self.parent.getSdAutourEtape(nom,self):
193 return 0, tr("Nommage du concept refuse : un concept de meme nom existe deja")
195 # Renommage du concept : Il suffit de changer son attribut nom pour le nommer
198 self.parent.updateConceptAfterEtape(self,self.sd)
200 return 1, tr("Nommage du concept effectue")
202 # Normalement l appel de isValid a mis a jour le concept produit (son type)
203 # Il suffit de specifier l attribut nom de sd pour le nommer si le nom n est pas
205 if self.parent.getSdAutourEtape(nom,self):
206 return 0, tr("Nommage du concept refuse : un concept de meme nom existe deja")
208 # Renommage du concept : Il suffit de changer son attribut nom pour le nommer
211 self.parent.updateConceptAfterEtape(self,self.sd)
213 return 1, tr("Nommage du concept effectue")
215 # Normalement on ne devrait pas passer ici
216 return 0, 'Normalement on ne devrait pas passer ici'
218 def getSdprods(self,nom_sd):
220 Fonction : retourne le concept produit par l etape de nom nom_sd
221 s il existe sinon None
224 if self.sd.nom == nom_sd:return self.sd
228 Rend l'etape courante active.
229 Il faut ajouter la sd si elle existe au contexte global du JDC
237 self.jdc.appendSdProd(self.sd)
240 CONNECTOR.Emit(self,"add",None)
241 CONNECTOR.Emit(self,"valid")
245 Rend l'etape courante inactive
246 Il faut supprimer la sd du contexte global du JDC
247 et de la liste des sd
252 self.jdc.delSdprod(self.sd)
253 self.jdc.deleteConceptAfterEtape(self,self.sd)
254 CONNECTOR.Emit(self,"supp",None)
255 CONNECTOR.Emit(self,"valid")
257 def controlSdprods(self,d):
259 Cette methode doit verifier que ses concepts produits ne sont pas
260 deja definis dans le contexte
261 Si c'est le cas, les concepts produits doivent etre supprimes
263 #print ("controlSdprods etape",d.keys(),self.sd and self.sd.nom,self.nom)
265 if self.sd.nom in d :
266 # Le concept est deja defini
267 if self.reuse and self.reuse is d[self.sd.nom]:
268 # Le concept est reutilise : situation normale
271 # Redefinition du concept, on l'annule
272 #XXX on pourrait simplement annuler son nom pour conserver les objets
273 # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
276 self.sd=self.reuse=self.sdnom=None
277 #supprime les references a sd dans les etapes suivantes
278 self.parent.deleteConceptAfterEtape(self,sd)
281 def supprimeSdprod(self,sd):
283 Supprime le concept produit sd s'il est produit par l'etape
285 if sd is not self.sd:return
288 self.parent.delSdprod(sd)
291 self.parent.deleteConcept(sd)
293 def supprimeSdProds(self):
296 Lors d'une destruction d'etape, detruit tous les concepts produits
297 Un operateur n a qu un concept produit
298 Une procedure n'en a aucun
299 Une macro en a en general plus d'un
302 #print "supprimeSdProds",self
303 if self.reuse is self.sd :return
304 # l'etape n'est pas reentrante
305 # le concept retourne par l'etape est a supprimer car il etait
308 self.parent.delSdprod(self.sd)
309 self.parent.deleteConcept(self.sd)
314 def updateConcept(self,sd):
315 for child in self.mcListe :
316 child.updateConcept(sd)
318 def deleteConcept(self,sd):
323 Mettre a jour les mots cles de l etape et eventuellement
324 le concept produit si reuse
325 suite a la disparition du concept sd
326 Seuls les mots cles simples MCSIMP font un traitement autre
327 que de transmettre aux fils
329 if self.reuse and self.reuse == sd:
330 self.sd=self.reuse=None
332 for child in self.mcListe :
333 child.deleteConcept(sd)
335 def replaceConcept(self,old_sd,sd):
338 - old_sd=concept remplace
339 - sd = nouveau concept
341 Mettre a jour les mots cles de l etape et eventuellement
342 le concept produit si reuse
343 suite au remplacement du concept old_sd
345 if self.reuse and self.reuse == old_sd:
346 self.sd=self.reuse=sd
348 for child in self.mcListe :
349 child.replaceConcept(old_sd,sd)
351 def resetContext(self):
354 def getNomsSdOperReentrant(self):
356 Retourne la liste des noms de concepts utilisesa l'interieur de la commande
357 qui sont du type que peut retourner cette commande
359 liste_sd = self.getSd_utilisees()
361 if type(self.definition.sd_prod) == types.FunctionType:
362 d=self.creeDictValeurs(self.mcListe)
364 classe_sd_prod = self.definition.sd_prod(*(), **d)
368 classe_sd_prod = self.definition.sd_prod
370 if sd.__class__ is classe_sd_prod : l_noms.append(sd.nom)
374 def getGenealogiePrecise(self):
377 def getNomDsXML(self):
378 # en xml on a un choice
380 for e in self.parent.etapes :
382 if e.nom == self.nom : index+=1
383 nomDsXML = self.nom + "[" + str(index) + "]"
387 def getGenealogie(self):
389 Retourne la liste des noms des ascendants de l'objet self
390 en s'arretant a la premiere ETAPE rencontree
394 def verifExistenceSd(self):
396 Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
397 avant etape, sinon enleve la referea ces concepts
399 #print "verifExistenceSd",self.sd
400 for motcle in self.mcListe :
401 motcle.verifExistenceSd()
403 def updateMcGlobal(self):
405 Met a jour les mots cles globaux enregistres dans l'etape
406 et dans le jdc parent.
407 Une etape ne peut pas etre globale. Elle se contente de passer
408 la requete a ses fils apres avoir reinitialise le dictionnaire
409 des mots cles globaux.
412 I_MCCOMPO.MCCOMPO.updateMcGlobal(self)
414 def updateConditionBloc(self):
416 Realise l'update des blocs conditionnels fils de self
418 self._updateConditionBloc()
420 def getObjetCommentarise(self,format):
422 Cette methode retourne un objet commande commentarisee
423 representant la commande self
426 g=generator.plugins[format]()
427 texte_commande = g.gener(self,format='beautifie')
428 # Il faut enlever la premiere ligne vide de texte_commande que
429 # rajoute le generator
430 # on construit l'objet COMMANDE_COMM repesentatif de self mais non
431 # enregistre dans le jdc (pas ajoute dans jdc.etapes)
433 pos=self.parent.etapes.index(self)
434 # on ajoute une fin à la commande pour pouvoir en commenter 2
435 texte_commande+='\nFin Commentaire'
436 commande_comment = commande_comm.COMMANDE_COMM(texte=texte_commande,
439 self.parent.suppEntite(self)
440 parent.addEntite(commande_comment,pos)
442 return commande_comment
445 """Le contenu de l'etape (mots cles, ...) a ete modifie"""
446 if self.nom=="DETRUIRE":
447 self.parent.controlContextApres(self)
451 #ATTENTION SURCHARGE: a garder en synchro ou a reintegrer dans le Noyau
452 def buildSd(self,nom):
454 Methode de Noyau surchargee pour poursuivre malgre tout
455 si une erreur se produit pendant la creation du concept produit
458 sd=Noyau.N_ETAPE.ETAPE.buildSd(self,nom)
459 except AsException as e :
460 # Une erreur s'est produite lors de la construction du concept
461 # Comme on est dans EFICAS, on essaie de poursuivre quand meme
462 # Si on poursuit, on a le choix entre deux possibilites :
463 # 1. on annule la sd associee a self
464 # 2. on la conserve mais il faut la retourner
465 # En plus il faut rendre coherents sdnom et sd.nom
468 self.state="unchanged"
473 #ATTENTION SURCHARGE: cette methode doit etre gardee en synchronisation avec Noyau
474 def makeRegister(self):
476 Initialise les attributs jdc, id, niveau et realise les
477 enregistrements necessaires
478 Pour EFICAS, on tient compte des niveaux
479 Surcharge la methode makeRegister du package Noyau
482 self.jdc = self.parent.getJdcRoot()
483 self.id= self.parent.register(self)
484 self.UserError=self.jdc.UserError
485 if self.definition.niveau :
486 # La definition est dans un niveau. En plus on
487 # l'enregistre dans le niveau
488 self.nom_niveau_definition = self.definition.niveau.nom
489 self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition]
490 self.niveau.register(self)
492 # La definition est au niveau global
493 self.nom_niveau_definition = 'JDC'
494 self.niveau=self.parent
496 self.jdc = self.parent =None
499 self.UserError="UserError"
502 cr= Validation.V_ETAPE.ETAPE.report(self)
503 #rafraichisst de la validite de l'etape (probleme avec l'ordre dans les macros : etape puis mots cles)
505 if not self.isValid() and self.nom == "INCLUDE" :
506 self.cr.fatal('Etape : {} ligne : {} {}'.format(self.nom, self.appel[0], tr("\n Include Invalide. \n ne sera pas pris en compte")))