1 # CONFIGURATION MANAGEMENT OF EDF VERSION
2 # ======================================================================
3 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
4 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
5 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
6 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
7 # (AT YOUR OPTION) ANY LATER VERSION.
9 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
10 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
11 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
12 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
15 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
16 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
19 # ======================================================================
25 myrepr.maxstring = 100
28 from Noyau.N_utils import repr_float
30 # Attention : les classes ASSD,.... peuvent etre surchargées
31 # dans le package Accas. Il faut donc prendre des précautions si
32 # on utilise les classes du Noyau pour faire des tests (isxxxx, ...)
33 # Si on veut créer des objets comme des CO avec les classes du noyau
34 # ils n'auront pas les conportements des autres packages (pb!!!)
35 # Il vaut mieux les importer d'Accas mais problème d'import circulaire,
36 # on ne peut pas les importer au début.
37 # On fait donc un import local quand c'est nécessaire (peut occasionner
38 # des pbs de prformance).
39 from Noyau.N_ASSD import ASSD,assd
40 from Noyau.N_GEOM import GEOM,geom
41 from Noyau.N_CO import CO
44 from Extensions import parametre
47 class MCSIMP(I_OBJECT.OBJECT):
50 Retourne le texte à afficher dans l'arbre représentant la valeur de l'objet
53 if self.valeur == None :
55 elif type(self.valeur) == types.FloatType :
56 # Traitement d'un flottant isolé
57 #txt = repr_float(self.valeur)
58 # Normalement str fait un travail correct
59 txt = str(self.valeur)
60 elif type(self.valeur) in (types.ListType,types.TupleType) :
61 # Traitement des listes
64 for val in self.valeur:
65 if type(val) == types.FloatType :
66 # CCAR : Normalement str fait un travail correct
67 #txt=txt + i*',' + repr_float(val)
68 txt=txt + i*',' + str(val)
69 elif isinstance(val,ASSD):
70 txt = txt + i*',' + val.get_name()
73 elif type(val) == types.InstanceType and val.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
74 txt = txt + i*','+ str(val)
76 txt = txt + i*','+ myrepr.repr(val)
80 # Traitement des autres cas
83 if type(txt) == types.InstanceType:
84 if isinstance(txt,parametre.PARAMETRE):
89 # txt peut etre une longue chaine sur plusieurs lignes.
90 # Il est possible de tronquer cette chaine au premier \n et
91 # de limiter la longueur de la chaine a 30 caracteres. Cependant
92 # ceci provoque une perte d'information pour l'utilisateur
93 # Pour le moment on retourne la chaine telle que
98 Retourne une chaîne de caractère représentant la valeur de self
101 if type(val) != types.TupleType :
103 return val.get_name()
110 s=s+item.get_name()+','
118 Méthode booléenne qui retourne 1 si l'objet attend un objet ASSD
119 qui n'existe pas encore (type CO()), 0 sinon
121 for typ in self.definition.type:
122 if type(typ) == types.ClassType :
123 if issubclass(typ,CO) :
129 Méthode booléenne qui retourne 1 si le MCS attend un objet de type ASSD
132 for typ in self.definition.type:
133 if type(typ) == types.ClassType :
134 if issubclass(typ,ASSD) and not issubclass(typ,GEOM):
138 def wait_assd_or_geom(self):
140 Retourne 1 si le mot-clé simple attend un objet de type
141 assd, ASSD, geom ou GEOM
142 Retourne 0 dans le cas contraire
144 for typ in self.definition.type:
145 if type(typ) == types.ClassType :
146 if typ.__name__ in ("GEOM","ASSD","geom","assd") or issubclass(typ,GEOM) :
152 Retourne 1 si le mot-clé simple attend un objet de type GEOM
153 Retourne 0 dans le cas contraire
155 for typ in self.definition.type:
156 if type(typ) == types.ClassType :
157 if issubclass(typ,GEOM) : return 1
162 Retourne 1 si le mot-clé simple attend un objet de type TXM
163 Retourne 0 dans le cas contraire
165 for typ in self.definition.type:
166 if typ == 'TXM' :return 1
169 def get_liste_valeurs(self):
172 if self.valeur == None:
174 elif type(self.valeur) == types.TupleType:
175 return list(self.valeur)
176 elif type(self.valeur) == types.ListType:
182 return self.definition.statut=='o'
184 # def set_valeur(self,new_valeur,evaluation='oui'):
186 # Remplace la valeur de self(si elle existe) par new_valeur
187 # - si evaluation = 'oui' :
188 # essaie d'évaluer new_valeur dans le contexte
189 # - si evaluation = 'non' :
190 # n'essaie pas d'évaluer (on stocke une string ou
191 # une valeur de la liste into )
193 # if evaluation == 'oui' and not self.wait_assd_or_geom():
194 # valeur,test = self.eval_valeur(new_valeur)
196 # self.val = new_valeur
197 # self.valeur = valeur
202 # # On n'a pas trouve de concept ni réussi à évaluer la valeur
204 # # Si le mot cle simple attend un type CO on crée un objet de ce
205 # # type de nom new_valeur
208 # # Pour avoir la classe CO avec tous ses comportements
209 # from Accas import CO
210 # self.valeur=CO(new_valeur)
212 # traceback.print_exc()
215 # self.val=self.valeur
218 # elif type(new_valeur)==types.StringType and self.wait_TXM():
220 # self.val = new_valeur
221 # self.valeur = new_valeur
227 # on ne fait aucune vérification ...
228 def set_valeur(self,new_valeur,evaluation='oui'):
230 self.valeur = new_valeur
231 self.val = new_valeur
235 def eval_valeur(self,new_valeur):
237 Essaie d'évaluer new_valeur comme une SD, une déclaration Python
238 ou un EVAL: Retourne la valeur évaluée (ou None) et le test de réussite (1 ou 0)
240 sd = self.jdc.get_contexte_avant(self.etape).get(new_valeur,None)
245 # On veut EVAL avec tous ses comportements. On utilise Accas. Perfs ??
246 from Accas import EVAL
249 objet = eval(new_valeur,d)
252 if CONTEXT.debug : traceback.print_exc()
255 def delete_concept(self,sd):
260 Met a jour la valeur du mot cle simple suite à la disparition
263 if type(self.valeur) == types.TupleType :
264 if sd in self.valeur:
265 self.valeur=list(self.valeur)
266 self.valeur.remove(sd)
268 elif type(self.valeur) == types.ListType:
269 if sd in self.valeur:
270 self.valeur.remove(sd)
273 if self.valeur == sd:
278 def replace_concept(self,old_sd,sd):
281 - old_sd=concept remplacé
284 Met a jour la valeur du mot cle simple suite au remplacement
287 if type(self.valeur) == types.TupleType :
288 if old_sd in self.valeur:
289 self.valeur=list(self.valeur)
290 i=self.valeur.index(old_sd)
293 elif type(self.valeur) == types.ListType:
294 if old_sd in self.valeur:
295 i=self.valeur.index(old_sd)
299 if self.valeur == old_sd:
305 """ Retourne une copie de self """
306 objet = self.makeobjet()
307 # il faut copier les listes et les tuples mais pas les autres valeurs
308 # possibles (réel,SD,...)
309 if type(self.valeur) in (types.ListType,types.TupleType):
310 objet.valeur = copy(self.valeur)
312 objet.valeur = self.valeur
313 objet.val = objet.valeur
317 return self.definition(val = None, nom = self.nom,parent = self.parent)
319 def get_sd_utilisees(self):
321 Retourne une liste qui contient la SD utilisée par self si c'est le cas
322 ou alors une liste vide
325 if type(self.valeur) == types.InstanceType:
326 #XXX Est ce différent de isinstance(self.valeur,ASSD) ??
327 if issubclass(self.valeur.__class__,ASSD) : l.append(self.valeur)
331 def set_valeur_co(self,nom_co):
333 Affecte à self l'objet de type CO et de nom nom_co
335 step=self.etape.parent
336 if nom_co == None or nom_co == '':
339 # Pour le moment on importe en local le CO de Accas.
340 # Si problème de perfs, il faudra faire autrement
342 # Avant de créer un concept il faut s'assurer du contexte : step
344 sd= step.get_sd_autour_etape(nom_co,self.etape,avec='oui')
346 # Si un concept du meme nom existe deja dans la portée de l'étape
347 # on ne crée pas le concept
348 return 0,"un concept de meme nom existe deja"
349 # Il n'existe pas de concept de meme nom. On peut donc le créer
350 # Il faut néanmoins que la méthode NommerSdProd de step gère les
351 # contextes en mode editeur
352 # Normalement la méthode du Noyau doit etre surchargée
353 # On déclare l'étape du mot clé comme etape courante pour NommerSdprod
354 cs= CONTEXT.get_current_step()
355 CONTEXT.unset_current_step()
356 CONTEXT.set_current_step(step)
357 step.set_etape_context(self.etape)
358 new_objet = CO(nom_co)
359 CONTEXT.unset_current_step()
360 CONTEXT.set_current_step(cs)
362 self.valeur = new_objet
366 # On force l'enregistrement de new_objet en tant que concept produit
367 # de la macro en appelant get_type_produit avec force=1
368 self.etape.get_type_produit(force=1)
369 return 1,"Concept créé"
371 def reparent(self,parent):
373 Cette methode sert a reinitialiser la parente de l'objet
377 self.etape=parent.etape
379 def verif_existence_sd(self):
381 Vérifie que les structures de données utilisées dans self existent bien dans le contexte
382 avant étape, sinon enlève la référence à ces concepts
384 l_sd_avant_etape = self.jdc.get_contexte_avant(self.etape).values()
385 if type(self.valeur) in (types.TupleType,types.ListType) :
387 for sd in self.valeur:
388 if isinstance(sd,ASSD) :
389 if sd in l_sd_avant_etape :
394 # Est ce init_modif ou init_modif_up
395 # Normalement init_modif va avec fin_modif
399 if isinstance(self.valeur,ASSD) :
400 if self.valeur not in l_sd_avant_etape :
405 def get_min_max(self):
407 Retourne les valeurs min et max admissibles pour la valeur de self
409 return self.definition.min,self.definition.max
414 Retourne le type attendu par le mot-clé simple
416 return self.definition.type
418 #ATTENTION SURCHARGE : toutes les methodes ci apres sont des surcharges du Noyau et de Validation
419 # Elles doivent etre reintegrees des que possible
421 def is_complexe(self,valeur):
422 """ Retourne 1 si valeur est un complexe, 0 sinon """
423 if type(valeur) == types.InstanceType :
424 #XXX je n'y touche pas pour ne pas tout casser mais il serait
425 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
426 if valeur.__class__.__name__ in ('EVAL','complexe','PARAMETRE_EVAL'):
428 elif valeur.__class__.__name__ in ('PARAMETRE',):
429 # il faut tester si la valeur du parametre est un entier
430 #XXX ne serait ce pas plutot complexe ???? sinon expliquer
431 return self.is_complexe(valeur.valeur)
433 print "Objet non reconnu dans is_complexe %s" %`valeur`
435 # Pour permettre l'utilisation de complexes Python
436 #elif type(valeur) == types.ComplexType:
438 elif type(valeur) == types.ListType :
439 # On n'autorise pas les listes de complexes
441 elif type(valeur) != types.TupleType :
442 # Un complexe doit etre un tuple
445 if len(valeur) != 3 :
448 if type(valeur[0]) != types.StringType : return 0
449 if string.strip(valeur[0]) not in ('RI','MP'):
452 if not self.is_reel(valeur[1]) or not self.is_reel(valeur[2]) : return 0
455 def is_reel(self,valeur):
457 Retourne 1 si valeur est un reel, 0 sinon
459 if type(valeur) == types.InstanceType :
460 #XXX je n'y touche pas pour ne pas tout casser mais il serait
461 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
462 #XXX ou valeur.is_reel()
463 #XXX ou encore valeur.compare(self.is_reel)
464 if valeur.__class__.__name__ in ('EVAL','reel','PARAMETRE_EVAL') :
466 elif valeur.__class__.__name__ in ('PARAMETRE',):
467 # il faut tester si la valeur du parametre est un réel
468 return self.is_reel(valeur.valeur)
470 print "Objet non reconnu dans is_reel %s" %`valeur`
472 elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
473 # ce n'est pas un réel
478 def is_entier(self,valeur):
479 """ Retourne 1 si valeur est un entier, 0 sinon """
480 if type(valeur) == types.InstanceType :
481 #XXX je n'y touche pas pour ne pas tout casser mais il serait
482 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
483 if valeur.__class__.__name__ in ('EVAL','entier','PARAMETRE_EVAL') :
485 elif valeur.__class__.__name__ in ('PARAMETRE',):
486 # il faut tester si la valeur du parametre est un entier
487 return self.is_entier(valeur.valeur)
489 print "Objet non reconnu dans is_reel %s" %`valeur`
491 elif type(valeur) not in (types.IntType,types.LongType):
492 # ce n'est pas un entier
497 def is_object_from(self,objet,classe):
499 Retourne 1 si valeur est un objet de la classe classe ou d'une
500 sous-classe de classe, 0 sinon
502 if type(objet) != types.InstanceType :
504 if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
510 if hasattr(self,'valid'):
516 def set_valid(self,valid):
517 old_valid=self.get_valid()
519 self.state = 'unchanged'
520 if not old_valid or old_valid != self.valid :
523 def isvalid(self,cr='non'):
525 Cette méthode retourne un indicateur de validité de l'objet de type MCSIMP
527 - 0 si l'objet est invalide
528 - 1 si l'objet est valide
530 Le paramètre cr permet de paramétrer le traitement. Si cr == 'oui'
531 la méthode construit également un comte-rendu de validation
532 dans self.cr qui doit avoir été créé préalablement.
534 if self.state == 'unchanged':
539 # verifiaction presence
540 if self.isoblig() and v == None :
542 self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé")))
548 self.cr.fatal("None n'est pas une valeur autorisée")
551 valid = self.verif_type(val=v,cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr)
553 # On verifie les validateurs s'il y en a et si necessaire (valid == 1)
555 if valid and self.definition.validators and not self.definition.validators.verif(self.valeur):
557 self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info())))
559 # fin des validateurs
562 self.set_valid(valid)
565 def verif_into(self,cr='non'):
567 Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
568 donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
569 entre val_min et val_max
571 if self.definition.into == None :
572 #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
573 if type(self.valeur)==types.TupleType :
575 for val in self.valeur :
576 if type(val)!=types.StringType and type(val)!=types.InstanceType:
577 test = test*self.isinintervalle(val,cr=cr)
581 if type(val)!=types.StringType and type(val)!=types.InstanceType:
582 return self.isinintervalle(self.valeur,cr=cr)
586 # on est dans le cas d'un ensemble discret de valeurs possibles (into)
587 # PN : pour résoudre le pb du copier /coller de la liste Ordonnee
588 # if type(self.valeur) == types.TupleType :
589 if type(self.valeur) in (types.ListType,types.TupleType) :
590 for e in self.valeur:
591 if e not in self.definition.into:
593 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
596 if self.valeur == None or self.valeur not in self.definition.into:
598 self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))