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
20 from __future__ import absolute_import
24 from Extensions.i18n import tr
25 from Extensions.eficas_exception import EficasException
27 from Noyau.N_utils import repr_float
29 from . import CONNECTOR
31 # Attention : les classes ASSD,.... peuvent etre surchargees
32 # dans le package Accas. Il faut donc prendre des precautions si
33 # on utilise les classes du Noyau pour faire des tests (isxxxx, ...)
34 # Si on veut creer des objets comme des CO avec les classes du noyau
35 # ils n'auront pas les conportements des autres packages (pb!!!)
36 # Il vaut mieux les importer d'Accas mais probleme d'import circulaire,
37 # on ne peut pas les importer au debut.
38 # On fait donc un import local quand c'est necessaire (peut occasionner
39 # des pbs de prformance).
40 from Noyau.N_ASSD import ASSD,assd
41 from Noyau.N_GEOM import GEOM,geom
42 from Noyau.N_CO import CO
43 from Accas.A_ASSD import UserASSD
47 from Extensions import parametre
48 from Extensions import param2
49 from . import I_OBJECT
50 from . import CONNECTOR
51 from .I_VALIDATOR import ValError,listProto
53 class MCSIMP(I_OBJECT.OBJECT):
56 def isValid(self,cr='non'):
57 if self.state == 'unchanged':
59 for type_permis in self.definition.type:
60 if hasattr(type_permis, "__class__") and type_permis.__class__.__name__ == 'Matrice':
61 self.monType=type_permis
62 return self.valideMatrice(cr=cr)
63 validite=Validation.V_MCSIMP.MCSIMP.isValid(self,cr=cr)
65 if self.definition.siValide != None and validite:
66 self.definition.siValide(self)
70 def getNomConcept(self):
74 nomconcept=p.getSdname()
78 nomconcept= p.object.getSdname()
87 Retourne le texte a afficher dans l'arbre representant la valeur de l'objet
91 if self.valeur == None :
93 elif type(self.valeur) == float :
94 # traitement d'un flottant isole
95 txt = str(self.valeur)
96 clefobj=self.getNomConcept()
97 if clefobj in self.jdc.appliEficas.dict_reels :
98 if self.valeur in self.jdc.appliEficas.dict_reels[clefobj]:
99 txt=self.jdc.appliEficas.dict_reels[clefobj][self.valeur]
100 elif type(self.valeur) in (list,tuple) :
101 if self.valeur==[] or self.valeur == (): return str(self.valeur)
102 # traitement des listes
105 for val in self.valeur:
106 if type(val) == float :
107 clefobj=self.getNomConcept()
108 if clefobj in self.jdc.appliEficas.dict_reels:
109 if val in self.jdc.appliEficas.dict_reels[clefobj]:
110 txt=txt + sep +self.jdc.appliEficas.dict_reels[clefobj][val]
112 txt=txt + sep + str(val)
114 txt=txt + sep + str(val)
116 if isinstance(val,tuple):
119 if isinstance(i, bytes) or isinstance(i,str) : texteVal = texteVal +"'"+str(i)+"',"
120 else : texteVal = texteVal + str(i)+','
121 texteVal=texteVal[:-1]+')'
123 if isinstance(val,bytes) or isinstance(val, str): texteVal="'"+str(val)+"'"
124 else :texteVal=str(val)
125 txt = txt + sep+ texteVal
127 ## if len(txt) > 200:
128 ## #ligne trop longue, on tronque
132 # cas des listes de tuples de longueur 1
133 if isinstance(val,tuple) and len(self.valeur) == 1 : txt=txt+','
136 # traitement des autres cas
137 txt = str(self.valeur)
139 # txt peut etre une longue chaine sur plusieurs lignes.
140 # Il est possible de tronquer cette chaine au premier \n et
141 # de limiter la longueur de la chaine a 30 caracteres. Cependant
142 # ceci provoque une perte d'information pour l'utilisateur
143 # Pour le moment on retourne la chaine telle que
148 Retourne une chaine de caractere representant la valeur de self
151 if type(val) == float :
152 clefobj=self.getNomConcept()
153 if clefobj in self.jdc.appliEficas.dict_reels :
154 if val in self.jdc.appliEficas.appliEficas.dict_reels[clefobj] :
155 return self.jdc.appliEficas.dict_reels[clefobj][val]
156 if type(val) != tuple :
162 if val ==() or val == [] : return val
166 s=s+item.getName()+','
173 for typ in self.definition.type:
175 if typ == bool: return True
182 Methode booleenne qui retourne 1 si l'objet attend un objet ASSD
183 qui n'existe pas encore (type CO()), 0 sinon
185 for typ in self.definition.type:
186 if type(typ) == type or isinstance(typ,type):
187 if issubclass(typ,CO) :
193 Methode booleenne qui retourne 1 si le MCS attend un objet de type ASSD ou UserASSD
196 for typ in self.definition.type:
197 if type(typ) == type or isinstance(typ,type):
198 if issubclass(typ,ASSD) and not issubclass(typ,GEOM) :
202 def waitUserAssd(self):
204 Methode booleenne qui retourne 1 si le MCS attend un objet de type ASSD
207 for typ in self.definition.type:
208 if type(typ) == type or isinstance(typ,type):
209 if issubclass(typ,UserASSD) :
213 def waitUserAssdEnCreation(self):
214 for typ in self.definition.type:
215 if typ == 'createObject' :
220 def waitAssdOrGeom(self):
222 Retourne 1 si le mot-cle simple attend un objet de type
223 assd, ASSD, geom ou GEOM
224 Retourne 0 dans le cas contraire
226 for typ in self.definition.type:
227 if type(typ) == type or isinstance(typ,type):
228 if typ.__name__ in ("GEOM","ASSD","geom","assd") or issubclass(typ,GEOM) :
234 Retourne 1 si le mot-cle simple attend un objet de type GEOM
235 Retourne 0 dans le cas contraire
237 for typ in self.definition.type:
238 if type(typ) == type or isinstance(typ,type):
239 if issubclass(typ,GEOM) : return 1
245 Retourne 1 si le mot-cle simple attend un objet de type TXM
246 Retourne 0 dans le cas contraire
248 for typ in self.definition.type:
249 if typ == 'TXM' :return 1
253 for ss_type in self.definition.type:
254 if repr(ss_type).find('Tuple') != -1 :
259 def getListeValeurs(self):
262 if self.valeur == None:
264 elif type(self.valeur) == tuple:
265 return list(self.valeur)
266 elif type(self.valeur) == list:
272 return self.definition.statut=='o'
274 def isImmuable(self):
275 return self.definition.homo=='constant'
277 def isInformation(self):
278 return self.definition.homo=='information'
282 def validVal(self,valeur):
284 Verifie que la valeur passee en argument (valeur) est valide
285 sans modifier la valeur courante
287 lval=listProto.adapt(valeur)
290 mess=tr("None n'est pas une valeur autorisee")
294 self.typeProto.adapt(val)
295 self.intoProto.adapt(val)
296 self.cardProto.adapt(lval)
297 if self.definition.validators:
298 self.definition.validators.convert(lval)
300 except ValError as e:
305 def validValeur(self,new_valeur):
307 Verifie que la valeur passee en argument (new_valeur) est valide
308 sans modifier la valeur courante (evite d'utiliser setValeur et est plus performant)
310 validite,mess=self.validVal(new_valeur)
313 def validValeurPartielle(self,new_valeur):
315 Verifie que la valeur passee en argument (new_valeur) est une liste partiellement valide
316 sans modifier la valeur courante du mot cle
320 for val in new_valeur:
321 self.typeProto.adapt(val)
322 self.intoProto.adapt(val)
323 #on ne verifie pas la cardinalite
324 if self.definition.validators:
325 validite=self.definition.validators.valideListePartielle(new_valeur)
326 except ValError as e:
331 def updateConditionBloc(self):
332 """ Met a jour les blocs conditionnels dependant du mot cle simple self
334 if self.definition.position == 'global' :
335 self.etape.deepUpdateConditionBloc()
336 elif self.definition.position == 'global_jdc' :
337 self.jdc.deepUpdateConditionBloc(self)
339 self.parent.updateConditionBloc()
341 def setValeur(self,new_valeur,evaluation='oui'):
343 self.valeur = new_valeur
344 self.val = new_valeur
345 if self.valeur and self.waitUserAssd() and not(self.waitUserAssdEnCreation()) :
346 if type(self.valeur) in (list,tuple):
347 for v in self.valeur : v.ajoutUtilisePar(self)
348 else : self.valeur.ajoutUtilisePar(self)
349 if self.isValid():self.setValeurObjPyxb(new_valeur)
350 self.updateConditionBloc()
351 self.etape.modified()
355 def evalValeur(self,new_valeur):
357 Essaie d'evaluer new_valeur comme une SD, une declaration Python
358 ou un EVAL: Retourne la valeur evaluee (ou None) et le test de reussite (1 ou 0)
360 sd = self.jdc.getSdAvantEtape(new_valeur,self.etape)
361 #sd = self.jdc.getContexteAvant(self.etape).get(new_valeur,None)
364 lsd = self.jdc.chercheListAvant(self.etape,new_valeur)
369 # On veut EVAL avec tous ses comportements. On utilise Accas. Perfs ??
372 objet = eval(new_valeur,d)
375 itparam=self.chercheItemParametre(new_valeur)
379 object=eval(new_valeur.valeur,d)
382 if CONTEXT.debug : traceback.print_exc()
385 def evalVal(self,new_valeur):
387 Tente d'evaluer new_valeur comme un objet du jdc (par appel a evalValItem)
388 ou comme une liste de ces memes objets
389 Si new_valeur contient au moins un separateur (,), tente l'evaluation sur
392 if new_valeur in ('True','False') and 'TXM' in self.definition.type :
393 valeur=self.evalValItem(str(new_valeur))
395 if type(new_valeur) in (list,tuple):
397 for item in new_valeur :
398 valeurretour.append(self.evalValItem(item))
401 valeur=self.evalValItem(new_valeur)
404 def evalValItem(self,new_valeur):
406 Tente d'evaluer new_valeur comme un concept, un parametre, un objet Python ou un UserASSD
407 Si c'est impossible retourne new_valeur inchange
408 argument new_valeur : string (nom de concept, de parametre, expression ou simple chaine)
410 if new_valeur in list(self.jdc.sdsDict.keys()) and self.waitUserAssd():
411 valeur=self.jdc.sdsDict[new_valeur]
413 elif self.etape and self.etape.parent:
414 valeur=self.etape.parent.evalInContext(new_valeur,self.etape)
421 #traceback.print_exc()
425 def chercheItemParametre (self,new_valeur):
427 nomparam=new_valeur[0:new_valeur.find("[")]
428 indice=new_valeur[new_valeur.find(u"[")+1:new_valeur.find(u"]")]
429 for p in self.jdc.params:
430 if p.nom == nomparam :
431 if int(indice) < len(p.getValeurs()):
432 itparam=parametre.ITEM_PARAMETRE(p,int(indice))
438 def updateConcept(self,sd):
439 if type(self.valeur) in (list,tuple) :
440 if sd in self.valeur:
443 for v in self.valeur : newVal.append(v.nom)
444 self.setValeurObjPyxb(newVal)
448 if sd == self.valeur:
449 if self.objPyxb : self.setValeurObjPyxb(sd.nom)
453 def deleteConcept(self,sd):
458 Met a jour la valeur du mot cle simple suite a la disparition
460 Attention aux matrices
463 if type(self.valeur) == tuple :
464 if sd in self.valeur:
466 self.valeur=list(self.valeur)
467 while sd in self.valeur : self.valeur.remove(sd)
470 for v in self.valeur : newVal.append(v.nom)
471 if newVal == [] : self.delObjPyxb()
472 else : self.setValeurObjPyxb(sd.nom)
474 elif type(self.valeur) == list:
475 if sd in self.valeur:
477 while sd in self.valeur : self.valeur.remove(sd)
480 if self.valeur == sd:
484 if self.objPyxb : self.setValeurObjPyxb()
486 # Glut Horrible pour les matrices ???
487 if sd.__class__.__name__== "variable":
488 for type_permis in self.definition.type:
489 #if type(type_permis) == types.InstanceType:
491 if type_permis.__class__.__name__ == 'Matrice' :
496 def replaceConcept(self,old_sd,sd):
499 - old_sd=concept remplace
502 Met a jour la valeur du mot cle simple suite au remplacement
505 print ("replaceConcept",old_sd,sd)
506 if type(self.valeur) == tuple :
507 if old_sd in self.valeur:
509 self.valeur=list(self.valeur)
510 i=self.valeur.index(old_sd)
513 elif type(self.valeur) == list:
514 if old_sd in self.valeur:
516 i=self.valeur.index(old_sd)
520 if self.valeur == old_sd:
526 def setValeurCo(self,nomCO):
528 Affecte a self l'objet de type CO et de nom nomCO
530 step=self.etape.parent
531 if nomCO == None or nomCO == '':
534 # Avant de creer un concept il faut s'assurer du contexte : step
536 sd= step.getSdAutourEtape(nomCO,self.etape,avec='oui')
538 # Si un concept du meme nom existe deja dans la portee de l'etape
539 # on ne cree pas le concept
540 return 0,tr("un concept de meme nom existe deja")
541 # Il n'existe pas de concept de meme nom. On peut donc le creer
542 # Il faut neanmoins que la methode NommerSdProd de step gere les
543 # contextes en mode editeur
544 # Normalement la methode du Noyau doit etre surchargee
545 # On declare l'etape du mot cle comme etape courante pour nommerSDProd
546 cs= CONTEXT.getCurrentStep()
547 CONTEXT.unsetCurrentStep()
548 CONTEXT.setCurrentStep(step)
549 step.setEtapeContext(self.etape)
550 new_objet = Accas.CO(nomCO)
551 CONTEXT.unsetCurrentStep()
552 CONTEXT.setCurrentStep(cs)
554 self.valeur = new_objet
556 # On force l'enregistrement de new_objet en tant que concept produit
557 # de la macro en appelant getType_produit avec force=1
558 self.etape.getType_produit(force=1)
561 #print "setValeurCo",new_objet
562 return 1,tr("Concept cree")
564 def verifExistenceSd(self):
566 Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
567 avant etape, sinon enleve la referea ces concepts
569 #print "verifExistenceSd"
570 # Attention : possible probleme avec include
571 # A priori il n'y a pas de raison de retirer les concepts non existants
572 # avant etape. En fait il s'agit uniquement eventuellement de ceux crees par une macro
573 l_sd_avant_etape = list(self.jdc.getContexteAvant(self.etape).values())
574 if type(self.valeur) in (tuple,list) :
576 for sd in self.valeur:
577 if isinstance(sd,ASSD) :
578 if sd in l_sd_avant_etape or self.etape.getSdprods(sd.nom) is sd:
582 if len(l) < len(self.valeur):
587 if isinstance(self.valeur,ASSD) :
588 if self.valeur not in l_sd_avant_etape and self.etape.getSdprods(self.valeur.nom) is None:
593 def renommeSdCree(self,nouveauNom):
594 print ( 'dans renommeSdCree', self.jdc.sdsDict, self.valeur)
595 if nouveauNom in self.jdc.sdsDict : return (0, 'concept deja existant')
596 if self.valeur == None : return (0, 'pb sur la valeur')
597 else : self.valeur.renomme(nouveauNom)
598 return (1, 'concept renomme')
600 def renommeSdCreeDsListe(self,objASSD, nouveauNom):
601 if nouveauNom in self.jdc.sdsDict : return (0, 'concept deja existant')
602 objASSD.renomme(nouveauNom)
603 return (1, 'concept renomme')
609 Retourne les valeurs min et max admissibles pour la valeur de self
611 return self.definition.min,self.definition.max
616 Retourne le type attendu par le mot-cle simple
618 return self.definition.type
620 def deleteMcGlobal(self):
621 """ Retire self des declarations globales
623 if self.definition.position == 'global' :
624 etape = self.getEtape()
626 del etape.mc_globaux[self.nom]
627 elif self.definition.position == 'global_jdc' :
631 del self.jdc.mc_globaux[self.nom]
634 def updateMcGlobal(self):
636 Met a jour les mots cles globaux enregistres dans l'etape parente
637 et dans le jdc parent.
638 Un mot cle simple peut etre global.
640 if self.definition.position == 'global' :
641 etape = self.getEtape()
643 etape.mc_globaux[self.nom]=self
644 elif self.definition.position == 'global_jdc' :
646 self.jdc.mc_globaux[self.nom]=self
648 def nbrColonnes(self):
649 genea = self.getGenealogie()
650 if "VALE_C" in genea and "DEFI_FONCTION" in genea : return 3
651 if "VALE" in genea and "DEFI_FONCTION" in genea : return 2
654 def valideItem(self,item):
655 """Valide un item isole. Cet item est candidata l'ajout a la liste existante"""
659 self.typeProto.adapt(item)
660 #on verifie les choix possibles
661 self.intoProto.adapt(item)
662 #on ne verifie pas la cardinalite
663 if self.definition.validators:
664 valid=self.definition.validators.verifItem(item)
665 except ValError as e:
666 #traceback.print_exc()
670 def verifType(self,item):
671 """Verifie le type d'un item de liste"""
674 self.typeProto.adapt(item)
675 #on verifie les choix possibles
676 self.intoProto.adapt(item)
677 #on ne verifie pas la cardinalite mais on verifie les validateurs
678 if self.definition.validators:
679 valid=self.definition.validators.verifItem(item)
682 except ValError as e:
683 #traceback.print_exc()
684 comment=tr(e.__str__())
688 def valideMatrice(self,cr):
689 #Attention, la matrice contient comme dernier tuple l ordre des variables
690 if self.valideEnteteMatrice()==False :
692 if cr == "oui" : self.cr.fatal(tr("La matrice n'a pas le bon entete"))
694 if self.monType.methodeCalculTaille != None :
695 MCSIMP.__dict__[self.monType.methodeCalculTaille](*(self,))
699 if len(self.valeur) == self.monType.nbLigs +1:
701 for i in range(len(self.valeur) -1):
702 if len(self.valeur[i])!= self.monType.nbCols:
711 self.cr.fatal(tr("La matrice n'est pas une matrice %(n_lign)d sur %(n_col)d", \
712 {'n_lign': self.monType.nbLigs, 'n_col': self.monType.nbCols}))
717 def nbDeVariables(self):
718 listeVariables=self.jdc.getVariables(self.etape)
719 self.monType.nbLigs=len(listeVariables)
720 self.monType.nbCols=len(listeVariables)
722 def valideEnteteMatrice(self):
723 if self.jdc.getDistributions(self.etape) == () or self.valeur == None : return 0
724 if self.jdc.getDistributions(self.etape) != self.valeur[0] : return 0
727 def changeEnteteMatrice(self):
728 a=[self.jdc.getDistributions(self.etape),]
729 for t in self.valeur[1:]:
734 def nbDeDistributions(self):
735 listeVariables=self.jdc.getDistributions(self.etape)
736 self.monType.nbLigs=len(listeVariables)
737 self.monType.nbCols=len(listeVariables)
739 def getNomDsXML(self):
740 nomDsXML=self.parent.getNomDsXML()+"."+self.nom
744 def verifTypeIhm(self,val,cr='non'):
749 traceback.print_exc()
751 return self.verifType(val,cr)
753 def verifTypeliste(self,val,cr='non') :
756 verif=verif+self.verifTypeIhm(v,cr)
759 def initModifUp(self):
760 Validation.V_MCSIMP.MCSIMP.initModifUp(self)
761 CONNECTOR.Emit(self,"valid")
764 print ('je suis dans deleteRef', self.nom)
765 if self.definition.creeDesObjets :
767 self.valeur.deleteReference()
769 for MC in self.valeur.utilisePar:
771 CONNECTOR.Emit(MC,"valid")