1 #@ MODIF V_MCSIMP Validation DATE 06/10/2003 AUTEUR DURAND C.DURAND
2 # CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
20 # ======================================================================
22 Ce module contient la classe mixin MCSIMP qui porte les méthodes
23 nécessaires pour réaliser la validation d'un objet de type MCSIMP
26 Une classe mixin porte principalement des traitements et est
27 utilisée par héritage multiple pour composer les traitements.
34 from Noyau import N_CR
35 from Noyau.N_Exception import AsException
40 Cette classe est quasiment identique à la classe originale d'EFICAS
41 a part quelques changements cosmétiques et des chagements pour la
42 faire fonctionner de facon plus autonome par rapport à l'environnement
45 A mon avis, il faudrait aller plus loin et réduire les dépendances
46 amont au strict nécessaire.
48 - Est il indispensable de faire l'évaluation de la valeur dans le contexte
49 du jdc dans cette classe.
51 - Ne pourrait on pas doter les objets en présence des méthodes suffisantes
52 pour éviter les tests un peu particuliers sur GEOM, PARAMETRE et autres. J'ai
53 d'ailleurs modifié la classe pour éviter l'import de GEOM
59 self.state='undetermined'
61 def isvalid(self,cr='non'):
63 Cette méthode retourne un indicateur de validité de l'objet
66 - 0 si l'objet est invalide
68 - 1 si l'objet est valide
70 Le pramètre cr permet de paramétrer le traitement. Si cr == 'oui'
71 la méthode construit également un comte-rendu de validation
72 dans self.cr qui doit avoir été créé préalablement.
74 if self.state == 'unchanged':
78 if hasattr(self,'valid'):
79 old_valid = self.valid
84 if self.isoblig() and v == None :
86 self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé")))
90 self.cr.fatal("None n'est pas une valeur autorisée")
94 valid = self.verif_type(val=v,cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr)
96 # On verifie les validateurs s'il y en a
98 if self.definition.validators and not self.definition.validators.verif(self.valeur):
100 self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info())))
102 # fin des validateurs
105 self.state = 'unchanged'
106 # Si la validité du mot clé a changé, on le signale à l'objet parent
107 if not old_valid or old_valid != self.valid :
112 """ indique si le mot-clé est obligatoire
114 return self.definition.statut=='o'
116 def verif_card(self,cr='non'):
118 un mot-clé simple ne peut etre répété :
119 la cardinalité ici s'entend par la vérification que le nombre d'arguments de self.valeur
120 est bien compris entre self.min et self.max dans le cas où il s'agit d'une liste
123 min=self.definition.min
124 max=self.definition.max
125 if type(self.valeur) in (types.ListType,types.TupleType) and 'C' not in self.definition.type :
126 if len(self.valeur) < min or len(self.valeur)>max:
128 self.cr.fatal("Nombre d'arguments %s incorrects pour %s (min = %s, max = %s)" %(`self.valeur`,self.nom,min,max))
131 if self.valeur == None :
133 # on n'a pas d'objet et on en attend au moins un
137 # on n'a qu'un objet et on en attend plus d'1
141 def verif_type(self,val=None,cr='non'):
144 Cette methode verifie que le type de l'argument val est en conformite avec celui
145 qui est declare dans la definition du mot cle simple.
146 Elle a plusieurs modes de fonctionnement liés à la valeur de cr.
147 Si cr vaut 'oui' : elle remplit le compte-rendu self.cr sinon elle ne le remplit pas.
148 PARAMETRE DE RETOUR :
149 Cette méthode retourne une valeur booléenne qui vaut 1 si le type de val est correct ou 0 sinon
155 self.cr.fatal("None n'est pas une valeur autorisée")
157 if type(valeur) == types.TupleType:
158 # on peut avoir à faire à un complexe ou une liste de valeurs ...
159 if self.is_complexe(valeur) : return 1
162 if not self.verif_type(val=val,cr=cr) : return 0
164 elif type(valeur) == types.ListType:
165 if self.is_complexe(valeur) : return 1
167 if not self.verif_type(val=val,cr=cr) : return 0
170 # on n'a pas de tuple ...il faut tester sur tous les types ou les valeurs possibles
171 # XXX Pourquoi into est il traité ici et pas seulement dans verif_into ???
172 if self.definition.into != None :
174 if valeur in self.definition.into :
178 self.cr.fatal("%s n'est pas une valeur autorisée" %valeur)
181 print "problème avec :",self.nom
182 print 'valeur =',valeur
184 for type_permis in self.definition.type:
185 if self.compare_type(valeur,type_permis) : return 1
186 # si on sort de la boucle précédente par ici c'est que l'on n'a trouvé aucun type valable --> valeur refusée
188 self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
191 def verif_into(self,cr='non'):
193 Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
194 donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
195 entre val_min et val_max
197 if self.definition.into == None :
198 #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
199 if type(self.valeur)==types.TupleType :
201 for val in self.valeur :
202 if type(val)!=types.StringType and type(val)!=types.InstanceType:
203 test = test*self.isinintervalle(val,cr=cr)
207 if type(val)!=types.StringType and type(val)!=types.InstanceType:
208 return self.isinintervalle(self.valeur,cr=cr)
212 # on est dans le cas d'un ensemble discret de valeurs possibles (into)
213 # PN : pour résoudre le pb du copier /coller de la liste Ordonnee
214 # if type(self.valeur) == types.TupleType :
215 if type(self.valeur) in (types.ListType,types.TupleType) :
216 for e in self.valeur:
217 if e not in self.definition.into:
219 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
222 if self.valeur == None or self.valeur not in self.definition.into:
224 self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
228 def is_complexe(self,valeur):
229 """ Retourne 1 si valeur est un complexe, 0 sinon """
230 if type(valeur) == types.StringType :
231 # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
232 #XXX Il serait peut etre plus judicieux d'appeler une méthode de self.jdc
233 #XXX qui retournerait l'objet résultat de l'évaluation
234 #XXX ou meme de faire cette evaluation a l'exterieur de cette classe ??
235 if not self.jdc :return 0
237 valeur = eval(valeur,self.jdc.g_context)
240 if type(valeur) == types.InstanceType :
241 #XXX je n'y touche pas pour ne pas tout casser mais il serait
242 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
243 if valeur.__class__.__name__ in ('EVAL','complexe'):
245 elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
246 # il faut tester si la valeur du parametre est un entier
247 #XXX ne serait ce pas plutot complexe ???? sinon expliquer
248 return self.is_entier(valeur.valeur)
250 print "Objet non reconnu dans is_complexe %s" %`valeur`
252 # Pour permettre l'utilisation de complexes Python
253 #elif type(valeur) == types.ComplexType:
255 elif type(valeur) != types.TupleType and type(valeur) != types.ListType:
258 if len(valeur) != 3 :
261 if type(valeur[0]) != types.StringType : return 0
262 if string.strip(valeur[0]) not in ('RI','MP'):
265 if not self.is_reel(valeur[1]) or not self.is_reel(valeur[2]) : return 0
268 def is_reel(self,valeur):
270 Retourne 1 si valeur est un reel, 0 sinon
272 if type(valeur) == types.StringType :
273 # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
274 if not self.jdc :return 0
276 valeur = eval(valeur,self.jdc.g_context)
279 if type(valeur) == types.InstanceType :
280 #XXX je n'y touche pas pour ne pas tout casser mais il serait
281 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
282 #XXX ou valeur.is_reel()
283 #XXX ou encore valeur.compare(self.is_reel)
284 if valeur.__class__.__name__ in ('EVAL','reel') :
286 elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
287 # il faut tester si la valeur du parametre est un réel
288 return self.is_reel(valeur.valeur)
290 print "Objet non reconnu dans is_reel %s" %`valeur`
292 elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
293 # ce n'est pas un réel
298 def is_entier(self,valeur):
299 """ Retourne 1 si valeur est un entier, 0 sinon """
300 if type(valeur) == types.StringType :
301 # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
302 if not self.jdc :return 0
304 valeur = eval(valeur,self.jdc.g_context)
307 if type(valeur) == types.InstanceType :
308 #XXX je n'y touche pas pour ne pas tout casser mais il serait
309 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
310 if valeur.__class__.__name__ in ('EVAL','entier') :
312 elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
313 # il faut tester si la valeur du parametre est un entier
314 return self.is_entier(valeur.valeur)
316 print "Objet non reconnu dans is_reel %s" %`valeur`
318 elif type(valeur) not in (types.IntType,types.LongType):
319 # ce n'est pas un entier
324 def is_shell(self,valeur):
326 Retourne 1 si valeur est un shell, 0 sinon
327 Pour l'instant aucune vérification n'est faite
328 On impose juste que valeur soit une string
330 if type(valeur) != types.StringType:
335 def is_object_from(self,objet,classe):
337 Retourne 1 si valeur est un objet de la classe classe ou d'une sous-classe de classe,
340 if type(objet) != types.InstanceType :
341 if type(objet) == types.StringType:
342 if not self.jdc :return 0
344 objet = eval(objet,self.jdc.g_context)
345 if type(objet) != types.InstanceType : return 0
350 if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
355 def compare_type(self,valeur,type_permis):
357 Fonction booléenne qui retourne 1 si valeur est du type type_permis, 0 sinon
359 if type(valeur) == types.InstanceType and valeur.__class__.__name__ == 'PARAMETRE':
360 if type(valeur.valeur) == types.TupleType :
361 # on a à faire à un PARAMETRE qui définit une liste d'items
362 # --> on teste sur la première car on n'accepte que les liste homogènes
363 valeur = valeur.valeur[0]
364 if type_permis == 'R':
365 return self.is_reel(valeur)
366 elif type_permis == 'I':
367 return self.is_entier(valeur)
368 elif type_permis == 'C':
369 return self.is_complexe(valeur)
370 elif type_permis == 'shell':
371 return self.is_shell(valeur)
372 elif type_permis == 'TXM':
373 if type(valeur) != types.InstanceType:
374 return type(valeur)==types.StringType
376 #XXX je n'y touche pas pour ne pas tout casser mais il serait
377 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('TXM'), par exemple
378 if valeur.__class__.__name__ == 'chaine' :
380 elif valeur.__class__.__name__ == 'PARAMETRE':
381 # il faut tester si la valeur du parametre est une string
382 return type(valeur.valeur)==types.StringType
385 elif type(type_permis) == types.ClassType:
386 # on ne teste pas certains objets de type GEOM , assd, ...
387 # On appelle la méthode de classe is_object de type_permis.
388 # Comme valeur peut etre de n'importe quel type on utilise la fonction (is_object.im_func)
389 # et non pas la methode (is_object) ce qui risquerait de provoquer des erreurs
390 if type_permis.is_object.im_func(valeur):
393 return self.is_object_from(valeur,type_permis)
395 print "Type non encore géré %s" %`type_permis`
396 print self.nom,self.parent.nom,self.jdc.fichier
398 def isinintervalle(self,valeur,cr='non'):
400 Booléenne qui retourne 1 si la valeur passée en argument est comprise dans
401 le domaine de définition donné dans le catalogue, 0 sinon.
403 if type(valeur) not in (types.IntType,types.FloatType,types.LongType) :
406 min = self.definition.val_min
407 max = self.definition.val_max
408 if min == '**': min = valeur -1
409 if max == '**': max = valeur +1
410 if valeur < min or valeur > max :
412 self.cr.fatal(string.join(("La valeur :",`valeur`," du mot-clé ",self.nom,\
413 " est en dehors du domaine de validité [",`min`,",",`max`,"]")))
418 def init_modif_up(self):
420 Propage l'état modifié au parent s'il existe et n'est l'objet
423 if self.parent and self.parent != self :
424 self.parent.state = 'modified'
427 """ génère le rapport de validation de self """
429 self.cr.debut = "Mot-clé simple : "+self.nom
430 self.cr.fin = "Fin Mot-clé simple : "+self.nom
431 self.state = 'modified'
433 self.isvalid(cr='oui')
434 except AsException,e:
435 if CONTEXT.debug : traceback.print_exc()
436 self.cr.fatal(string.join(("Mot-clé simple : ",self.nom,str(e))))