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 if self.definition.siValide != None :
68 self.definition.siValide(self)
69 return Validation.V_MCSIMP.MCSIMP.isvalid(self,cr=cr)
71 def GetNomConcept(self):
75 nomconcept=p.get_sdname()
79 nomconcept= p.object.get_sdname()
88 Retourne le texte a afficher dans l'arbre representant la valeur de l'objet
92 if self.valeur == None :
94 elif type(self.valeur) == float :
95 # Traitement d'un flottant isole
96 txt = str(self.valeur)
97 clefobj=self.GetNomConcept()
98 if clefobj in self.jdc.appli.appliEficas.dict_reels :
99 if self.valeur in self.jdc.appli.appliEficas.dict_reels[clefobj]:
100 txt=self.jdc.appli.appliEficas.dict_reels[clefobj][self.valeur]
101 elif type(self.valeur) in (list,tuple) :
102 if self.valeur==[] or self.valeur == (): return str(self.valeur)
103 # Traitement des listes
106 for val in self.valeur:
107 if type(val) == float :
108 clefobj=self.GetNomConcept()
109 if clefobj in self.jdc.appli.appliEficas.dict_reels:
110 if val in self.jdc.appli.appliEficas.dict_reels[clefobj]:
111 txt=txt + sep +self.jdc.appli.appliEficas.dict_reels[clefobj][val]
113 txt=txt + sep + str(val)
115 txt=txt + sep + str(val)
117 if isinstance(val,tuple):
120 if isinstance(i, bytes) : texteVal = texteVal +"'"+str(i)+"',"
121 else : texteVal = texteVal + str(i)+','
122 texteVal=texteVal[:-1]+')'
124 if isinstance(val,bytes): texteVal="'"+str(val)+"'"
125 else :texteVal=str(val)
126 txt = txt + sep+ texteVal
128 ## if len(txt) > 200:
129 ## #ligne trop longue, on tronque
133 # cas des listes de tuples de longueur 1
134 if isinstance(val,tuple) and len(self.valeur) == 1 : txt=txt+','
137 # Traitement des autres cas
138 txt = str(self.valeur)
140 # txt peut etre une longue chaine sur plusieurs lignes.
141 # Il est possible de tronquer cette chaine au premier \n et
142 # de limiter la longueur de la chaine a 30 caracteres. Cependant
143 # ceci provoque une perte d'information pour l'utilisateur
144 # Pour le moment on retourne la chaine telle que
149 Retourne une chaine de caractere representant la valeur de self
152 if type(val) == float :
153 clefobj=self.GetNomConcept()
154 if clefobj in self.jdc.appli.appliEficas.dict_reels :
155 if val in self.jdc.appli.appliEficas.appliEficas.dict_reels[clefobj] :
156 return self.jdc.appli.appliEficas.dict_reels[clefobj][val]
157 if type(val) != tuple :
159 return val.get_name()
163 if val ==() or val == [] : return val
167 s=s+item.get_name()+','
174 for typ in self.definition.type:
176 if typ == bool: return True
183 Methode booleenne qui retourne 1 si l'objet attend un objet ASSD
184 qui n'existe pas encore (type CO()), 0 sinon
186 for typ in self.definition.type:
187 if type(typ) == type or isinstance(typ,type):
188 if issubclass(typ,CO) :
194 Methode booleenne qui retourne 1 si le MCS attend un objet de type ASSD
197 for typ in self.definition.type:
198 if type(typ) == type or isinstance(typ,type):
199 if issubclass(typ,ASSD) and not issubclass(typ,GEOM):
203 def wait_assd_or_geom(self):
205 Retourne 1 si le mot-cle simple attend un objet de type
206 assd, ASSD, geom ou GEOM
207 Retourne 0 dans le cas contraire
209 for typ in self.definition.type:
210 if type(typ) == type or isinstance(typ,type):
211 if typ.__name__ in ("GEOM","ASSD","geom","assd") or issubclass(typ,GEOM) :
217 Retourne 1 si le mot-cle simple attend un objet de type GEOM
218 Retourne 0 dans le cas contraire
220 for typ in self.definition.type:
221 if type(typ) == type or isinstance(typ,type):
222 if issubclass(typ,GEOM) : return 1
228 Retourne 1 si le mot-cle simple attend un objet de type TXM
229 Retourne 0 dans le cas contraire
231 for typ in self.definition.type:
232 if typ == 'TXM' :return 1
235 def get_liste_valeurs(self):
238 if self.valeur == None:
240 elif type(self.valeur) == tuple:
241 return list(self.valeur)
242 elif type(self.valeur) == list:
248 return self.definition.statut=='o'
250 def isImmuable(self):
251 return self.definition.homo=='constant'
253 def isInformation(self):
254 return self.definition.homo=='information'
258 def valid_val(self,valeur):
260 Verifie que la valeur passee en argument (valeur) est valide
261 sans modifier la valeur courante
263 lval=listProto.adapt(valeur)
266 mess=tr("None n'est pas une valeur autorisee")
270 self.typeProto.adapt(val)
271 self.intoProto.adapt(val)
272 self.cardProto.adapt(lval)
273 if self.definition.validators:
274 self.definition.validators.convert(lval)
276 except ValError as e:
281 def valid_valeur(self,new_valeur):
283 Verifie que la valeur passee en argument (new_valeur) est valide
284 sans modifier la valeur courante (evite d'utiliser set_valeur et est plus performant)
286 validite,mess=self.valid_val(new_valeur)
289 def valid_valeur_partielle(self,new_valeur):
291 Verifie que la valeur passee en argument (new_valeur) est une liste partiellement valide
292 sans modifier la valeur courante du mot cle
296 for val in new_valeur:
297 self.typeProto.adapt(val)
298 self.intoProto.adapt(val)
299 #on ne verifie pas la cardinalite
300 if self.definition.validators:
301 validite=self.definition.validators.valide_liste_partielle(new_valeur)
302 except ValError as e:
307 def update_condition_bloc(self):
308 """ Met a jour les blocs conditionnels dependant du mot cle simple self
310 if self.definition.position == 'global' :
311 self.etape.deep_update_condition_bloc()
312 elif self.definition.position == 'global_jdc' :
313 self.jdc.deep_update_condition_bloc()
315 self.parent.update_condition_bloc()
317 def set_valeur(self,new_valeur,evaluation='oui'):
318 #print "set_valeur",new_valeur
320 self.valeur = new_valeur
321 self.val = new_valeur
322 self.update_condition_bloc()
323 self.etape.modified()
327 def eval_valeur(self,new_valeur):
329 Essaie d'evaluer new_valeur comme une SD, une declaration Python
330 ou un EVAL: Retourne la valeur evaluee (ou None) et le test de reussite (1 ou 0)
332 sd = self.jdc.get_sd_avant_etape(new_valeur,self.etape)
333 #sd = self.jdc.get_contexte_avant(self.etape).get(new_valeur,None)
337 lsd = self.jdc.cherche_list_avant(self.etape,new_valeur)
342 # On veut EVAL avec tous ses comportements. On utilise Accas. Perfs ??
345 objet = eval(new_valeur,d)
348 itparam=self.cherche_item_parametre(new_valeur)
352 object=eval(new_valeur.valeur,d)
355 if CONTEXT.debug : traceback.print_exc()
358 def eval_val(self,new_valeur):
360 Tente d'evaluer new_valeur comme un objet du jdc (par appel a eval_val_item)
361 ou comme une liste de ces memes objets
362 Si new_valeur contient au moins un separateur (,), tente l'evaluation sur
365 if new_valeur in ('True','False') and 'TXM' in self.definition.type :
366 valeur=self.eval_val_item(str(new_valeur))
368 if type(new_valeur) in (list,tuple):
370 for item in new_valeur :
371 valeurretour.append(self.eval_val_item(item))
374 valeur=self.eval_val_item(new_valeur)
377 def eval_val_item(self,new_valeur):
379 Tente d'evaluer new_valeur comme un concept, un parametre, un objet Python
380 Si c'est impossible retourne new_valeur inchange
381 argument new_valeur : string (nom de concept, de parametre, expression ou simple chaine)
383 if self.etape and self.etape.parent:
384 valeur=self.etape.parent.eval_in_context(new_valeur,self.etape)
391 #traceback.print_exc()
395 def cherche_item_parametre (self,new_valeur):
397 nomparam=new_valeur[0:new_valeur.find("[")]
398 indice=new_valeur[new_valeur.find(u"[")+1:new_valeur.find(u"]")]
399 for p in self.jdc.params:
400 if p.nom == nomparam :
401 if int(indice) < len(p.get_valeurs()):
402 itparam=parametre.ITEM_PARAMETRE(p,int(indice))
408 def update_concept(self,sd):
409 if type(self.valeur) in (list,tuple) :
410 if sd in self.valeur:
414 if sd == self.valeur:
418 def delete_concept(self,sd):
423 Met a jour la valeur du mot cle simple suite a la disparition
425 Attention aux matrices
427 if type(self.valeur) == tuple :
428 if sd in self.valeur:
430 self.valeur=list(self.valeur)
431 self.valeur.remove(sd)
433 elif type(self.valeur) == list:
434 if sd in self.valeur:
436 self.valeur.remove(sd)
439 if self.valeur == sd:
444 # Glut Horrible pour les matrices ???
445 if sd.__class__.__name__== "variable":
446 for type_permis in self.definition.type:
447 #if type(type_permis) == types.InstanceType:
449 if type_permis.__class__.__name__ == 'Matrice' :
454 def replace_concept(self,old_sd,sd):
457 - old_sd=concept remplace
460 Met a jour la valeur du mot cle simple suite au remplacement
463 #print "replace_concept",old_sd,sd
464 if type(self.valeur) == tuple :
465 if old_sd in self.valeur:
467 self.valeur=list(self.valeur)
468 i=self.valeur.index(old_sd)
471 elif type(self.valeur) == list:
472 if old_sd in self.valeur:
474 i=self.valeur.index(old_sd)
478 if self.valeur == old_sd:
484 def set_valeur_co(self,nom_co):
486 Affecte a self l'objet de type CO et de nom nom_co
488 #print "set_valeur_co",nom_co
489 step=self.etape.parent
490 if nom_co == None or nom_co == '':
493 # Avant de creer un concept il faut s'assurer du contexte : step
495 sd= step.get_sd_autour_etape(nom_co,self.etape,avec='oui')
497 # Si un concept du meme nom existe deja dans la portee de l'etape
498 # on ne cree pas le concept
499 return 0,tr("un concept de meme nom existe deja")
500 # Il n'existe pas de concept de meme nom. On peut donc le creer
501 # Il faut neanmoins que la methode NommerSdProd de step gere les
502 # contextes en mode editeur
503 # Normalement la methode du Noyau doit etre surchargee
504 # On declare l'etape du mot cle comme etape courante pour NommerSdprod
505 cs= CONTEXT.get_current_step()
506 CONTEXT.unset_current_step()
507 CONTEXT.set_current_step(step)
508 step.set_etape_context(self.etape)
509 new_objet = Accas.CO(nom_co)
510 CONTEXT.unset_current_step()
511 CONTEXT.set_current_step(cs)
513 self.valeur = new_objet
515 # On force l'enregistrement de new_objet en tant que concept produit
516 # de la macro en appelant get_type_produit avec force=1
517 self.etape.get_type_produit(force=1)
520 #print "set_valeur_co",new_objet
521 return 1,tr("Concept cree")
523 def verif_existence_sd(self):
525 Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
526 avant etape, sinon enleve la referea ces concepts
528 #print "verif_existence_sd"
529 # Attention : possible probleme avec include
530 # A priori il n'y a pas de raison de retirer les concepts non existants
531 # avant etape. En fait il s'agit uniquement eventuellement de ceux crees par une macro
532 l_sd_avant_etape = list(self.jdc.get_contexte_avant(self.etape).values())
533 if type(self.valeur) in (tuple,list) :
535 for sd in self.valeur:
536 if isinstance(sd,ASSD) :
537 if sd in l_sd_avant_etape or self.etape.get_sdprods(sd.nom) is sd:
541 if len(l) < len(self.valeur):
546 if isinstance(self.valeur,ASSD) :
547 if self.valeur not in l_sd_avant_etape and self.etape.get_sdprods(self.valeur.nom) is None:
552 def get_min_max(self):
554 Retourne les valeurs min et max admissibles pour la valeur de self
556 return self.definition.min,self.definition.max
561 Retourne le type attendu par le mot-cle simple
563 return self.definition.type
565 def delete_mc_global(self):
566 """ Retire self des declarations globales
568 if self.definition.position == 'global' :
569 etape = self.get_etape()
571 del etape.mc_globaux[self.nom]
572 elif self.definition.position == 'global_jdc' :
573 del self.jdc.mc_globaux[self.nom]
575 def update_mc_global(self):
577 Met a jour les mots cles globaux enregistres dans l'etape parente
578 et dans le jdc parent.
579 Un mot cle simple peut etre global.
581 if self.definition.position == 'global' :
582 etape = self.get_etape()
584 etape.mc_globaux[self.nom]=self
585 elif self.definition.position == 'global_jdc' :
587 self.jdc.mc_globaux[self.nom]=self
589 def nbrColonnes(self):
590 genea = self.get_genealogie()
591 if "VALE_C" in genea and "DEFI_FONCTION" in genea : return 3
592 if "VALE" in genea and "DEFI_FONCTION" in genea : return 2
595 def valide_item(self,item):
596 """Valide un item isole. Cet item est candidata l'ajout a la liste existante"""
600 self.typeProto.adapt(item)
601 #on verifie les choix possibles
602 self.intoProto.adapt(item)
603 #on ne verifie pas la cardinalite
604 if self.definition.validators:
605 valid=self.definition.validators.verif_item(item)
606 except ValError as e:
607 #traceback.print_exc()
611 def verif_type(self,item):
612 """Verifie le type d'un item de liste"""
615 self.typeProto.adapt(item)
616 #on verifie les choix possibles
617 self.intoProto.adapt(item)
618 #on ne verifie pas la cardinalite mais on verifie les validateurs
619 if self.definition.validators:
620 valid=self.definition.validators.verif_item(item)
623 except ValError as e:
624 #traceback.print_exc()
625 comment=tr(e.__str__())
629 def valideMatrice(self,cr):
630 #Attention, la matrice contient comme dernier tuple l ordre des variables
631 if self.valideEnteteMatrice()==False :
633 if cr == "oui" : self.cr.fatal(tr("La matrice n'a pas le bon entete"))
635 if self.monType.methodeCalculTaille != None :
636 MCSIMP.__dict__[self.monType.methodeCalculTaille](*(self,))
640 if len(self.valeur) == self.monType.nbLigs +1:
642 for i in range(len(self.valeur) -1):
643 if len(self.valeur[i])!= self.monType.nbCols:
652 self.cr.fatal(tr("La matrice n'est pas une matrice %(n_lign)d sur %(n_col)d", \
653 {'n_lign': self.monType.nbLigs, 'n_col': self.monType.nbCols}))
658 def NbDeVariables(self):
659 listeVariables=self.jdc.get_variables(self.etape)
660 self.monType.nbLigs=len(listeVariables)
661 self.monType.nbCols=len(listeVariables)
663 def valideEnteteMatrice(self):
664 if self.jdc.get_distributions(self.etape) == () or self.valeur == None : return 0
665 if self.jdc.get_distributions(self.etape) != self.valeur[0] : return 0
668 def changeEnteteMatrice(self):
669 a=[self.jdc.get_distributions(self.etape),]
670 for t in self.valeur[1:]:
675 def NbDeDistributions(self):
676 listeVariables=self.jdc.get_distributions(self.etape)
677 self.monType.nbLigs=len(listeVariables)
678 self.monType.nbCols=len(listeVariables)
680 #--------------------------------------------------------------------------------
682 #ATTENTION SURCHARGE : toutes les methodes ci apres sont des surcharges du Noyau et de Validation
683 # Elles doivent etre reintegrees des que possible
686 def verif_typeihm(self,val,cr='non'):
691 traceback.print_exc()
693 return self.verif_type(val,cr)
695 def verif_typeliste(self,val,cr='non') :
698 verif=verif+self.verif_typeihm(v,cr)
701 def init_modif_up(self):
702 Validation.V_MCSIMP.MCSIMP.init_modif_up(self)
703 CONNECTOR.Emit(self,"valid")