1 # -*- coding: utf-8 -*-
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
20 from __future__ import absolute_import
24 from six.moves.reprlib import Repr
25 from Extensions.i18n import tr
26 from Extensions.eficas_exception import EficasException
27 from six.moves import range
29 myrepr.maxstring = 100
32 from Noyau.N_utils import repr_float
34 from . import CONNECTOR
36 # Attention : les classes ASSD,.... peuvent etre surchargees
37 # dans le package Accas. Il faut donc prendre des precautions si
38 # on utilise les classes du Noyau pour faire des tests (isxxxx, ...)
39 # Si on veut creer des objets comme des CO avec les classes du noyau
40 # ils n'auront pas les conportements des autres packages (pb!!!)
41 # Il vaut mieux les importer d'Accas mais probleme d'import circulaire,
42 # on ne peut pas les importer au debut.
43 # On fait donc un import local quand c'est necessaire (peut occasionner
44 # des pbs de prformance).
45 from Noyau.N_ASSD import ASSD,assd
46 from Noyau.N_GEOM import GEOM,geom
47 from Noyau.N_CO import CO
51 from Extensions import parametre
52 from Extensions import param2
53 from . import I_OBJECT
54 from . import CONNECTOR
55 from .I_VALIDATOR import ValError,listProto
57 class MCSIMP(I_OBJECT.OBJECT):
60 def isValid(self,cr='non'):
61 if self.state == 'unchanged':
63 for type_permis in self.definition.type:
64 if hasattr(type_permis, "__class__") and type_permis.__class__.__name__ == 'Matrice':
65 self.monType=type_permis
66 return self.valideMatrice(cr=cr)
67 validite=Validation.V_MCSIMP.MCSIMP.isValid(self,cr=cr)
68 if self.definition.siValide != None and validite:
69 self.definition.siValide(self)
72 def getNomConcept(self):
76 nomconcept=p.getSdname()
80 nomconcept= p.object.getSdname()
89 Retourne le texte a afficher dans l'arbre representant la valeur de l'objet
93 if self.valeur == None :
95 elif type(self.valeur) == float :
96 # traitement d'un flottant isole
97 txt = str(self.valeur)
98 clefobj=self.getNomConcept()
99 if clefobj in self.jdc.appli.appliEficas.dict_reels :
100 if self.valeur in self.jdc.appli.appliEficas.dict_reels[clefobj]:
101 txt=self.jdc.appli.appliEficas.dict_reels[clefobj][self.valeur]
102 elif type(self.valeur) in (list,tuple) :
103 if self.valeur==[] or self.valeur == (): return str(self.valeur)
104 # traitement des listes
107 for val in self.valeur:
108 if type(val) == float :
109 clefobj=self.getNomConcept()
110 if clefobj in self.jdc.appli.appliEficas.dict_reels:
111 if val in self.jdc.appli.appliEficas.dict_reels[clefobj]:
112 txt=txt + sep +self.jdc.appli.appliEficas.dict_reels[clefobj][val]
114 txt=txt + sep + str(val)
116 txt=txt + sep + str(val)
118 if isinstance(val,tuple):
121 if isinstance(i, bytes) : texteVal = texteVal +"'"+str(i)+"',"
122 else : texteVal = texteVal + str(i)+','
123 texteVal=texteVal[:-1]+')'
125 if isinstance(val,bytes): texteVal="'"+str(val)+"'"
126 else :texteVal=str(val)
127 txt = txt + sep+ texteVal
129 ## if len(txt) > 200:
130 ## #ligne trop longue, on tronque
134 # cas des listes de tuples de longueur 1
135 if isinstance(val,tuple) and len(self.valeur) == 1 : txt=txt+','
138 # traitement des autres cas
139 txt = str(self.valeur)
141 # txt peut etre une longue chaine sur plusieurs lignes.
142 # Il est possible de tronquer cette chaine au premier \n et
143 # de limiter la longueur de la chaine a 30 caracteres. Cependant
144 # ceci provoque une perte d'information pour l'utilisateur
145 # Pour le moment on retourne la chaine telle que
150 Retourne une chaine de caractere representant la valeur de self
153 if type(val) == float :
154 clefobj=self.getNomConcept()
155 if clefobj in self.jdc.appli.appliEficas.dict_reels :
156 if val in self.jdc.appli.appliEficas.appliEficas.dict_reels[clefobj] :
157 return self.jdc.appli.appliEficas.dict_reels[clefobj][val]
158 if type(val) != tuple :
164 if val ==() or val == [] : return val
168 s=s+item.getName()+','
175 for typ in self.definition.type:
177 if typ == bool: return True
184 Methode booleenne qui retourne 1 si l'objet attend un objet ASSD
185 qui n'existe pas encore (type CO()), 0 sinon
187 for typ in self.definition.type:
188 if type(typ) == type or isinstance(typ,type):
189 if issubclass(typ,CO) :
195 Methode booleenne qui retourne 1 si le MCS attend un objet de type ASSD
198 for typ in self.definition.type:
199 if type(typ) == type or isinstance(typ,type):
200 if issubclass(typ,ASSD) and not issubclass(typ,GEOM):
204 def waitAssdOrGeom(self):
206 Retourne 1 si le mot-cle simple attend un objet de type
207 assd, ASSD, geom ou GEOM
208 Retourne 0 dans le cas contraire
210 for typ in self.definition.type:
211 if type(typ) == type or isinstance(typ,type):
212 if typ.__name__ in ("GEOM","ASSD","geom","assd") or issubclass(typ,GEOM) :
218 Retourne 1 si le mot-cle simple attend un objet de type GEOM
219 Retourne 0 dans le cas contraire
221 for typ in self.definition.type:
222 if type(typ) == type or isinstance(typ,type):
223 if issubclass(typ,GEOM) : return 1
229 Retourne 1 si le mot-cle simple attend un objet de type TXM
230 Retourne 0 dans le cas contraire
232 for typ in self.definition.type:
233 if typ == 'TXM' :return 1
237 for ss_type in self.definition.type:
238 if repr(ss_type).find('Tuple') != -1 :
243 def getListeValeurs(self):
246 if self.valeur == None:
248 elif type(self.valeur) == tuple:
249 return list(self.valeur)
250 elif type(self.valeur) == list:
256 return self.definition.statut=='o'
258 def isImmuable(self):
259 return self.definition.homo=='constant'
261 def isInformation(self):
262 return self.definition.homo=='information'
266 def validVal(self,valeur):
268 Verifie que la valeur passee en argument (valeur) est valide
269 sans modifier la valeur courante
271 lval=listProto.adapt(valeur)
274 mess=tr("None n'est pas une valeur autorisee")
278 self.typeProto.adapt(val)
279 self.intoProto.adapt(val)
280 self.cardProto.adapt(lval)
281 if self.definition.validators:
282 self.definition.validators.convert(lval)
284 except ValError as e:
289 def validValeur(self,new_valeur):
291 Verifie que la valeur passee en argument (new_valeur) est valide
292 sans modifier la valeur courante (evite d'utiliser setValeur et est plus performant)
294 validite,mess=self.validVal(new_valeur)
297 def validValeurPartielle(self,new_valeur):
299 Verifie que la valeur passee en argument (new_valeur) est une liste partiellement valide
300 sans modifier la valeur courante du mot cle
304 for val in new_valeur:
305 self.typeProto.adapt(val)
306 self.intoProto.adapt(val)
307 #on ne verifie pas la cardinalite
308 if self.definition.validators:
309 validite=self.definition.validators.valideListePartielle(new_valeur)
310 except ValError as e:
315 def updateConditionBloc(self):
316 """ Met a jour les blocs conditionnels dependant du mot cle simple self
318 if self.definition.position == 'global' :
319 self.etape.deepUpdateConditionBloc()
320 elif self.definition.position == 'global_jdc' :
321 self.jdc.deepUpdateConditionBloc()
323 self.parent.updateConditionBloc()
325 def setValeur(self,new_valeur,evaluation='oui'):
326 print ("setValeur Ihm/IMCSIMP ",new_valeur)
328 self.valeur = new_valeur
329 self.val = new_valeur
330 self.setValeurObjPyxb(new_valeur)
331 self.updateConditionBloc()
332 self.etape.modified()
336 def evalValeur(self,new_valeur):
338 Essaie d'evaluer new_valeur comme une SD, une declaration Python
339 ou un EVAL: Retourne la valeur evaluee (ou None) et le test de reussite (1 ou 0)
341 sd = self.jdc.getSdAvantEtape(new_valeur,self.etape)
342 #sd = self.jdc.getContexteAvant(self.etape).get(new_valeur,None)
346 lsd = self.jdc.chercheListAvant(self.etape,new_valeur)
351 # On veut EVAL avec tous ses comportements. On utilise Accas. Perfs ??
354 objet = eval(new_valeur,d)
357 itparam=self.chercheItemParametre(new_valeur)
361 object=eval(new_valeur.valeur,d)
364 if CONTEXT.debug : traceback.print_exc()
367 def evalVal(self,new_valeur):
369 Tente d'evaluer new_valeur comme un objet du jdc (par appel a evalValItem)
370 ou comme une liste de ces memes objets
371 Si new_valeur contient au moins un separateur (,), tente l'evaluation sur
374 if new_valeur in ('True','False') and 'TXM' in self.definition.type :
375 valeur=self.evalValItem(str(new_valeur))
377 if type(new_valeur) in (list,tuple):
379 for item in new_valeur :
380 valeurretour.append(self.evalValItem(item))
383 valeur=self.evalValItem(new_valeur)
386 def evalValItem(self,new_valeur):
388 Tente d'evaluer new_valeur comme un concept, un parametre, un objet Python
389 Si c'est impossible retourne new_valeur inchange
390 argument new_valeur : string (nom de concept, de parametre, expression ou simple chaine)
392 if self.etape and self.etape.parent:
393 valeur=self.etape.parent.evalInContext(new_valeur,self.etape)
400 #traceback.print_exc()
404 def chercheItemParametre (self,new_valeur):
406 nomparam=new_valeur[0:new_valeur.find("[")]
407 indice=new_valeur[new_valeur.find(u"[")+1:new_valeur.find(u"]")]
408 for p in self.jdc.params:
409 if p.nom == nomparam :
410 if int(indice) < len(p.getValeurs()):
411 itparam=parametre.ITEM_PARAMETRE(p,int(indice))
417 def updateConcept(self,sd):
418 if type(self.valeur) in (list,tuple) :
419 if sd in self.valeur:
423 if sd == self.valeur:
427 def deleteConcept(self,sd):
432 Met a jour la valeur du mot cle simple suite a la disparition
434 Attention aux matrices
436 if type(self.valeur) == tuple :
437 if sd in self.valeur:
439 self.valeur=list(self.valeur)
440 self.valeur.remove(sd)
442 elif type(self.valeur) == list:
443 if sd in self.valeur:
445 self.valeur.remove(sd)
448 if self.valeur == sd:
453 # Glut Horrible pour les matrices ???
454 if sd.__class__.__name__== "variable":
455 for type_permis in self.definition.type:
456 #if type(type_permis) == types.InstanceType:
458 if type_permis.__class__.__name__ == 'Matrice' :
463 def replaceConcept(self,old_sd,sd):
466 - old_sd=concept remplace
469 Met a jour la valeur du mot cle simple suite au remplacement
472 #print "replaceConcept",old_sd,sd
473 if type(self.valeur) == tuple :
474 if old_sd in self.valeur:
476 self.valeur=list(self.valeur)
477 i=self.valeur.index(old_sd)
480 elif type(self.valeur) == list:
481 if old_sd in self.valeur:
483 i=self.valeur.index(old_sd)
487 if self.valeur == old_sd:
493 def setValeurCo(self,nom_co):
495 Affecte a self l'objet de type CO et de nom nom_co
497 #print "setValeurCo",nom_co
498 step=self.etape.parent
499 if nom_co == None or nom_co == '':
502 # Avant de creer un concept il faut s'assurer du contexte : step
504 sd= step.getSdAutourEtape(nom_co,self.etape,avec='oui')
506 # Si un concept du meme nom existe deja dans la portee de l'etape
507 # on ne cree pas le concept
508 return 0,tr("un concept de meme nom existe deja")
509 # Il n'existe pas de concept de meme nom. On peut donc le creer
510 # Il faut neanmoins que la methode NommerSdProd de step gere les
511 # contextes en mode editeur
512 # Normalement la methode du Noyau doit etre surchargee
513 # On declare l'etape du mot cle comme etape courante pour NommerSdprod
514 cs= CONTEXT.getCurrentStep()
515 CONTEXT.unsetCurrentStep()
516 CONTEXT.setCurrentStep(step)
517 step.setEtapeContext(self.etape)
518 new_objet = Accas.CO(nom_co)
519 CONTEXT.unsetCurrentStep()
520 CONTEXT.setCurrentStep(cs)
522 self.valeur = new_objet
524 # On force l'enregistrement de new_objet en tant que concept produit
525 # de la macro en appelant getType_produit avec force=1
526 self.etape.getType_produit(force=1)
529 #print "setValeurCo",new_objet
530 return 1,tr("Concept cree")
532 def verifExistenceSd(self):
534 Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
535 avant etape, sinon enleve la referea ces concepts
537 #print "verifExistenceSd"
538 # Attention : possible probleme avec include
539 # A priori il n'y a pas de raison de retirer les concepts non existants
540 # avant etape. En fait il s'agit uniquement eventuellement de ceux crees par une macro
541 l_sd_avant_etape = list(self.jdc.getContexteAvant(self.etape).values())
542 if type(self.valeur) in (tuple,list) :
544 for sd in self.valeur:
545 if isinstance(sd,ASSD) :
546 if sd in l_sd_avant_etape or self.etape.getSdprods(sd.nom) is sd:
550 if len(l) < len(self.valeur):
555 if isinstance(self.valeur,ASSD) :
556 if self.valeur not in l_sd_avant_etape and self.etape.getSdprods(self.valeur.nom) is None:
563 Retourne les valeurs min et max admissibles pour la valeur de self
565 return self.definition.min,self.definition.max
570 Retourne le type attendu par le mot-cle simple
572 return self.definition.type
574 def deleteMcGlobal(self):
575 """ Retire self des declarations globales
577 if self.definition.position == 'global' :
578 etape = self.getEtape()
580 del etape.mc_globaux[self.nom]
581 elif self.definition.position == 'global_jdc' :
582 del self.jdc.mc_globaux[self.nom]
584 def updateMcGlobal(self):
586 Met a jour les mots cles globaux enregistres dans l'etape parente
587 et dans le jdc parent.
588 Un mot cle simple peut etre global.
590 if self.definition.position == 'global' :
591 etape = self.getEtape()
593 etape.mc_globaux[self.nom]=self
594 elif self.definition.position == 'global_jdc' :
596 self.jdc.mc_globaux[self.nom]=self
598 def nbrColonnes(self):
599 genea = self.getGenealogie()
600 if "VALE_C" in genea and "DEFI_FONCTION" in genea : return 3
601 if "VALE" in genea and "DEFI_FONCTION" in genea : return 2
604 def valideItem(self,item):
605 """Valide un item isole. Cet item est candidata l'ajout a la liste existante"""
609 self.typeProto.adapt(item)
610 #on verifie les choix possibles
611 self.intoProto.adapt(item)
612 #on ne verifie pas la cardinalite
613 if self.definition.validators:
614 valid=self.definition.validators.verifItem(item)
615 except ValError as e:
616 #traceback.print_exc()
620 def verifType(self,item):
621 """Verifie le type d'un item de liste"""
624 self.typeProto.adapt(item)
625 #on verifie les choix possibles
626 self.intoProto.adapt(item)
627 #on ne verifie pas la cardinalite mais on verifie les validateurs
628 if self.definition.validators:
629 valid=self.definition.validators.verifItem(item)
632 except ValError as e:
633 #traceback.print_exc()
634 comment=tr(e.__str__())
638 def valideMatrice(self,cr):
639 #Attention, la matrice contient comme dernier tuple l ordre des variables
640 if self.valideEnteteMatrice()==False :
642 if cr == "oui" : self.cr.fatal(tr("La matrice n'a pas le bon entete"))
644 if self.monType.methodeCalculTaille != None :
645 MCSIMP.__dict__[self.monType.methodeCalculTaille](*(self,))
649 if len(self.valeur) == self.monType.nbLigs +1:
651 for i in range(len(self.valeur) -1):
652 if len(self.valeur[i])!= self.monType.nbCols:
661 self.cr.fatal(tr("La matrice n'est pas une matrice %(n_lign)d sur %(n_col)d", \
662 {'n_lign': self.monType.nbLigs, 'n_col': self.monType.nbCols}))
667 def nbDeVariables(self):
668 listeVariables=self.jdc.getVariables(self.etape)
669 self.monType.nbLigs=len(listeVariables)
670 self.monType.nbCols=len(listeVariables)
672 def valideEnteteMatrice(self):
673 if self.jdc.getDistributions(self.etape) == () or self.valeur == None : return 0
674 if self.jdc.getDistributions(self.etape) != self.valeur[0] : return 0
677 def changeEnteteMatrice(self):
678 a=[self.jdc.getDistributions(self.etape),]
679 for t in self.valeur[1:]:
684 def nNbDeDistributions(self):
685 listeVariables=self.jdc.getDistributions(self.etape)
686 self.monType.nbLigs=len(listeVariables)
687 self.monType.nbCols=len(listeVariables)
689 #--------------------------------------------------------------------------------
691 #ATTENTION SURCHARGE : toutes les methodes ci apres sont des surcharges du Noyau et de Validation
692 # Elles doivent etre reintegrees des que possible
695 def verifTypeIhm(self,val,cr='non'):
700 traceback.print_exc()
702 return self.verifType(val,cr)
704 def verifTypeliste(self,val,cr='non') :
707 verif=verif+self.verifTypeIhm(v,cr)
710 def initModifUp(self):
711 Validation.V_MCSIMP.MCSIMP.initModifUp(self)
712 CONNECTOR.Emit(self,"valid")