1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013 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 return Validation.V_MCSIMP.MCSIMP.isvalid(self,cr=cr)
69 def GetNomConcept(self):
73 nomconcept=p.get_sdname()
77 nomconcept= p.object.get_sdname()
86 Retourne le texte a afficher dans l'arbre representant la valeur de l'objet
90 if self.valeur == None :
92 elif type(self.valeur) == float :
93 # Traitement d'un flottant isole
94 txt = str(self.valeur)
95 clefobj=self.GetNomConcept()
96 if clefobj in self.jdc.appli.appliEficas.dict_reels :
97 if self.valeur in self.jdc.appli.appliEficas.dict_reels[clefobj]:
98 txt=self.jdc.appli.appliEficas.dict_reels[clefobj][self.valeur]
99 elif type(self.valeur) in (list,tuple) :
100 if self.valeur==[] or self.valeur == (): return str(self.valeur)
101 # Traitement des listes
104 for val in self.valeur:
105 if type(val) == float :
106 clefobj=self.GetNomConcept()
107 if clefobj in self.jdc.appli.appliEficas.dict_reels:
108 if val in self.jdc.appli.appliEficas.dict_reels[clefobj]:
109 txt=txt + sep +self.jdc.appli.appliEficas.dict_reels[clefobj][val]
111 txt=txt + sep + str(val)
113 txt=txt + sep + str(val)
115 if isinstance(val,tuple):
118 if isinstance(i, bytes) : texteVal = texteVal +"'"+str(i)+"',"
119 else : texteVal = texteVal + str(i)+','
120 texteVal=texteVal[:-1]+')'
122 if isinstance(val,bytes): texteVal="'"+str(val)+"'"
123 else :texteVal=str(val)
124 txt = txt + sep+ texteVal
126 ## if len(txt) > 200:
127 ## #ligne trop longue, on tronque
131 # cas des listes de tuples de longueur 1
132 if isinstance(val,tuple) and len(self.valeur) == 1 : txt=txt+','
135 # Traitement des autres cas
136 txt = str(self.valeur)
138 # txt peut etre une longue chaine sur plusieurs lignes.
139 # Il est possible de tronquer cette chaine au premier \n et
140 # de limiter la longueur de la chaine a 30 caracteres. Cependant
141 # ceci provoque une perte d'information pour l'utilisateur
142 # Pour le moment on retourne la chaine telle que
147 Retourne une chaine de caractere representant la valeur de self
150 if type(val) == float :
151 clefobj=self.GetNomConcept()
152 if clefobj in self.jdc.appli.appliEficas.dict_reels :
153 if val in self.jdc.appli.appliEficas.appliEficas.dict_reels[clefobj] :
154 return self.jdc.appli.appliEficas.dict_reels[clefobj][val]
155 if type(val) != tuple :
157 return val.get_name()
161 if val ==() or val == [] : return val
165 s=s+item.get_name()+','
172 for typ in self.definition.type:
174 if typ == bool: return True
181 Methode booleenne qui retourne 1 si l'objet attend un objet ASSD
182 qui n'existe pas encore (type CO()), 0 sinon
184 for typ in self.definition.type:
185 if type(typ) == type or isinstance(typ,type):
186 if issubclass(typ,CO) :
192 Methode booleenne qui retourne 1 si le MCS attend un objet de type ASSD
195 for typ in self.definition.type:
196 if type(typ) == type or isinstance(typ,type):
197 if issubclass(typ,ASSD) and not issubclass(typ,GEOM):
201 def wait_assd_or_geom(self):
203 Retourne 1 si le mot-cle simple attend un objet de type
204 assd, ASSD, geom ou GEOM
205 Retourne 0 dans le cas contraire
207 for typ in self.definition.type:
208 if type(typ) == type or isinstance(typ,type):
209 if typ.__name__ in ("GEOM","ASSD","geom","assd") or issubclass(typ,GEOM) :
215 Retourne 1 si le mot-cle simple attend un objet de type GEOM
216 Retourne 0 dans le cas contraire
218 for typ in self.definition.type:
219 if type(typ) == type or isinstance(typ,type):
220 if issubclass(typ,GEOM) : return 1
226 Retourne 1 si le mot-cle simple attend un objet de type TXM
227 Retourne 0 dans le cas contraire
229 for typ in self.definition.type:
230 if typ == 'TXM' :return 1
233 def get_liste_valeurs(self):
236 if self.valeur == None:
238 elif type(self.valeur) == tuple:
239 return list(self.valeur)
240 elif type(self.valeur) == list:
246 return self.definition.statut=='o'
248 def isImmuable(self):
249 return self.definition.homo=='constant'
251 def isInformation(self):
252 return self.definition.homo=='information'
256 def valid_val(self,valeur):
258 Verifie que la valeur passee en argument (valeur) est valide
259 sans modifier la valeur courante
261 lval=listProto.adapt(valeur)
264 mess=tr("None n'est pas une valeur autorisee")
268 self.typeProto.adapt(val)
269 self.intoProto.adapt(val)
270 self.cardProto.adapt(lval)
271 if self.definition.validators:
272 self.definition.validators.convert(lval)
274 except ValError as e:
279 def valid_valeur(self,new_valeur):
281 Verifie que la valeur passee en argument (new_valeur) est valide
282 sans modifier la valeur courante (evite d'utiliser set_valeur et est plus performant)
284 validite,mess=self.valid_val(new_valeur)
287 def valid_valeur_partielle(self,new_valeur):
289 Verifie que la valeur passee en argument (new_valeur) est une liste partiellement valide
290 sans modifier la valeur courante du mot cle
294 for val in new_valeur:
295 self.typeProto.adapt(val)
296 self.intoProto.adapt(val)
297 #on ne verifie pas la cardinalite
298 if self.definition.validators:
299 validite=self.definition.validators.valide_liste_partielle(new_valeur)
300 except ValError as e:
305 def update_condition_bloc(self):
306 """ Met a jour les blocs conditionnels dependant du mot cle simple self
308 if self.definition.position == 'global' :
309 self.etape.deep_update_condition_bloc()
310 elif self.definition.position == 'global_jdc' :
311 self.jdc.deep_update_condition_bloc()
313 self.parent.update_condition_bloc()
315 def set_valeur(self,new_valeur,evaluation='oui'):
316 #print "set_valeur",new_valeur
318 self.valeur = new_valeur
319 self.val = new_valeur
320 self.update_condition_bloc()
321 self.etape.modified()
325 def eval_valeur(self,new_valeur):
327 Essaie d'evaluer new_valeur comme une SD, une declaration Python
328 ou un EVAL: Retourne la valeur evaluee (ou None) et le test de reussite (1 ou 0)
330 sd = self.jdc.get_sd_avant_etape(new_valeur,self.etape)
331 #sd = self.jdc.get_contexte_avant(self.etape).get(new_valeur,None)
335 lsd = self.jdc.cherche_list_avant(self.etape,new_valeur)
340 # On veut EVAL avec tous ses comportements. On utilise Accas. Perfs ??
343 objet = eval(new_valeur,d)
346 itparam=self.cherche_item_parametre(new_valeur)
350 object=eval(new_valeur.valeur,d)
353 if CONTEXT.debug : traceback.print_exc()
356 def eval_val(self,new_valeur):
358 Tente d'evaluer new_valeur comme un objet du jdc (par appel a eval_val_item)
359 ou comme une liste de ces memes objets
360 Si new_valeur contient au moins un separateur (,), tente l'evaluation sur
363 if new_valeur in ('True','False') and 'TXM' in self.definition.type :
364 valeur=self.eval_val_item(str(new_valeur))
366 if type(new_valeur) in (list,tuple):
368 for item in new_valeur :
369 valeurretour.append(self.eval_val_item(item))
372 valeur=self.eval_val_item(new_valeur)
375 def eval_val_item(self,new_valeur):
377 Tente d'evaluer new_valeur comme un concept, un parametre, un objet Python
378 Si c'est impossible retourne new_valeur inchange
379 argument new_valeur : string (nom de concept, de parametre, expression ou simple chaine)
381 if self.etape and self.etape.parent:
382 valeur=self.etape.parent.eval_in_context(new_valeur,self.etape)
389 #traceback.print_exc()
393 def cherche_item_parametre (self,new_valeur):
395 nomparam=new_valeur[0:new_valeur.find("[")]
396 indice=new_valeur[new_valeur.find(u"[")+1:new_valeur.find(u"]")]
397 for p in self.jdc.params:
398 if p.nom == nomparam :
399 if int(indice) < len(p.get_valeurs()):
400 itparam=parametre.ITEM_PARAMETRE(p,int(indice))
406 def update_concept(self,sd):
407 if type(self.valeur) in (list,tuple) :
408 if sd in self.valeur:
412 if sd == self.valeur:
416 def delete_concept(self,sd):
421 Met a jour la valeur du mot cle simple suite a la disparition
423 Attention aux matrices
425 if type(self.valeur) == tuple :
426 if sd in self.valeur:
428 self.valeur=list(self.valeur)
429 self.valeur.remove(sd)
431 elif type(self.valeur) == list:
432 if sd in self.valeur:
434 self.valeur.remove(sd)
437 if self.valeur == sd:
442 # Glut Horrible pour les matrices ???
443 if sd.__class__.__name__== "variable":
444 for type_permis in self.definition.type:
445 if type(type_permis) == types.InstanceType:
446 if type_permis.__class__.__name__ == 'Matrice' :
451 def replace_concept(self,old_sd,sd):
454 - old_sd=concept remplace
457 Met a jour la valeur du mot cle simple suite au remplacement
460 #print "replace_concept",old_sd,sd
461 if type(self.valeur) == tuple :
462 if old_sd in self.valeur:
464 self.valeur=list(self.valeur)
465 i=self.valeur.index(old_sd)
468 elif type(self.valeur) == list:
469 if old_sd in self.valeur:
471 i=self.valeur.index(old_sd)
475 if self.valeur == old_sd:
481 def set_valeur_co(self,nom_co):
483 Affecte a self l'objet de type CO et de nom nom_co
485 #print "set_valeur_co",nom_co
486 step=self.etape.parent
487 if nom_co == None or nom_co == '':
490 # Avant de creer un concept il faut s'assurer du contexte : step
492 sd= step.get_sd_autour_etape(nom_co,self.etape,avec='oui')
494 # Si un concept du meme nom existe deja dans la portee de l'etape
495 # on ne cree pas le concept
496 return 0,tr("un concept de meme nom existe deja")
497 # Il n'existe pas de concept de meme nom. On peut donc le creer
498 # Il faut neanmoins que la methode NommerSdProd de step gere les
499 # contextes en mode editeur
500 # Normalement la methode du Noyau doit etre surchargee
501 # On declare l'etape du mot cle comme etape courante pour NommerSdprod
502 cs= CONTEXT.get_current_step()
503 CONTEXT.unset_current_step()
504 CONTEXT.set_current_step(step)
505 step.set_etape_context(self.etape)
506 new_objet = Accas.CO(nom_co)
507 CONTEXT.unset_current_step()
508 CONTEXT.set_current_step(cs)
510 self.valeur = new_objet
512 # On force l'enregistrement de new_objet en tant que concept produit
513 # de la macro en appelant get_type_produit avec force=1
514 self.etape.get_type_produit(force=1)
517 #print "set_valeur_co",new_objet
518 return 1,tr("Concept cree")
520 def verif_existence_sd(self):
522 Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
523 avant etape, sinon enleve la referea ces concepts
525 #print "verif_existence_sd"
526 # Attention : possible probleme avec include
527 # A priori il n'y a pas de raison de retirer les concepts non existants
528 # avant etape. En fait il s'agit uniquement eventuellement de ceux crees par une macro
529 l_sd_avant_etape = list(self.jdc.get_contexte_avant(self.etape).values())
530 if type(self.valeur) in (tuple,list) :
532 for sd in self.valeur:
533 if isinstance(sd,ASSD) :
534 if sd in l_sd_avant_etape or self.etape.get_sdprods(sd.nom) is sd:
538 if len(l) < len(self.valeur):
543 if isinstance(self.valeur,ASSD) :
544 if self.valeur not in l_sd_avant_etape and self.etape.get_sdprods(self.valeur.nom) is None:
549 def get_min_max(self):
551 Retourne les valeurs min et max admissibles pour la valeur de self
553 return self.definition.min,self.definition.max
558 Retourne le type attendu par le mot-cle simple
560 return self.definition.type
562 def delete_mc_global(self):
563 """ Retire self des declarations globales
565 if self.definition.position == 'global' :
566 etape = self.get_etape()
568 del etape.mc_globaux[self.nom]
569 elif self.definition.position == 'global_jdc' :
570 del self.jdc.mc_globaux[self.nom]
572 def update_mc_global(self):
574 Met a jour les mots cles globaux enregistres dans l'etape parente
575 et dans le jdc parent.
576 Un mot cle simple peut etre global.
578 if self.definition.position == 'global' :
579 etape = self.get_etape()
581 etape.mc_globaux[self.nom]=self
582 elif self.definition.position == 'global_jdc' :
584 self.jdc.mc_globaux[self.nom]=self
586 def nbrColonnes(self):
587 genea = self.get_genealogie()
588 if "VALE_C" in genea and "DEFI_FONCTION" in genea : return 3
589 if "VALE" in genea and "DEFI_FONCTION" in genea : return 2
592 def valide_item(self,item):
593 """Valide un item isole. Cet item est candidata l'ajout a la liste existante"""
597 self.typeProto.adapt(item)
598 #on verifie les choix possibles
599 self.intoProto.adapt(item)
600 #on ne verifie pas la cardinalite
601 if self.definition.validators:
602 valid=self.definition.validators.verif_item(item)
603 except ValError as e:
604 #traceback.print_exc()
608 def verif_type(self,item):
609 """Verifie le type d'un item de liste"""
612 self.typeProto.adapt(item)
613 #on verifie les choix possibles
614 self.intoProto.adapt(item)
615 #on ne verifie pas la cardinalite mais on verifie les validateurs
616 if self.definition.validators:
617 valid=self.definition.validators.verif_item(item)
620 except ValError as e:
621 #traceback.print_exc()
622 comment=tr(e.__str__())
626 def valideMatrice(self,cr):
627 #Attention, la matrice contient comme dernier tuple l ordre des variables
628 if self.valideEnteteMatrice()==False :
630 if cr == "oui" : self.cr.fatal(tr("La matrice n'a pas le bon entete"))
632 if self.monType.methodeCalculTaille != None :
633 MCSIMP.__dict__[self.monType.methodeCalculTaille](*(self,))
637 if len(self.valeur) == self.monType.nbLigs +1:
639 for i in range(len(self.valeur) -1):
640 if len(self.valeur[i])!= self.monType.nbCols:
649 self.cr.fatal(tr("La matrice n'est pas une matrice %(n_lign)d sur %(n_col)d", \
650 {'n_lign': self.monType.nbLigs, 'n_col': self.monType.nbCols}))
655 def NbDeVariables(self):
656 listeVariables=self.jdc.get_variables(self.etape)
657 self.monType.nbLigs=len(listeVariables)
658 self.monType.nbCols=len(listeVariables)
660 def valideEnteteMatrice(self):
661 if self.jdc.get_distributions(self.etape) == () or self.valeur == None : return 0
662 if self.jdc.get_distributions(self.etape) != self.valeur[0] : return 0
665 def changeEnteteMatrice(self):
666 a=[self.jdc.get_distributions(self.etape),]
667 for t in self.valeur[1:]:
672 def NbDeDistributions(self):
673 listeVariables=self.jdc.get_distributions(self.etape)
674 self.monType.nbLigs=len(listeVariables)
675 self.monType.nbCols=len(listeVariables)
677 #--------------------------------------------------------------------------------
679 #ATTENTION SURCHARGE : toutes les methodes ci apres sont des surcharges du Noyau et de Validation
680 # Elles doivent etre reintegrees des que possible
683 def verif_typeihm(self,val,cr='non'):
688 traceback.print_exc()
690 return self.verif_type(val,cr)
692 def verif_typeliste(self,val,cr='non') :
695 verif=verif+self.verif_typeihm(v,cr)
698 def init_modif_up(self):
699 Validation.V_MCSIMP.MCSIMP.init_modif_up(self)
700 CONNECTOR.Emit(self,"valid")