1 #@ MODIF V_MCSIMP Validation DATE 09/09/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
67 - 1 si l'objet est valide
69 Le pramètre cr permet de paramétrer le traitement. Si cr == 'oui'
70 la méthode construit également un comte-rendu de validation
71 dans self.cr qui doit avoir été créé préalablement.
73 if self.state == 'unchanged':
77 if hasattr(self,'valid'):
78 old_valid = self.valid
83 if self.isoblig() and v == None :
85 self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé")))
90 self.cr.fatal("None n'est pas une valeur autorisée")
93 valid = self.verif_type(val=v,cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr)
95 # On verifie les validateurs s'il y en a
97 if self.definition.validators and not self.definition.validators.verif(self.valeur):
99 self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info())))
101 # fin des validateurs
104 self.state = 'unchanged'
105 # Si la validité du mot clé a changé, on le signale à l'objet parent
106 if not old_valid or old_valid != self.valid :
111 """ indique si le mot-clé est obligatoire
113 return self.definition.statut=='o'
115 def verif_card(self,cr='non'):
117 un mot-clé simple ne peut etre répété :
118 la cardinalité ici s'entend par la vérification que le nombre d'arguments de self.valeur
119 est bien compris entre self.min et self.max dans le cas où il s'agit d'une liste
122 min=self.definition.min
123 max=self.definition.max
124 if type(self.valeur) in (types.ListType,types.TupleType) and 'C' not in self.definition.type :
125 if len(self.valeur) < min or len(self.valeur)>max:
127 self.cr.fatal("Nombre d'arguments %s incorrects pour %s (min = %s, max = %s)" %(`self.valeur`,self.nom,min,max))
130 if self.valeur == None :
132 # on n'a pas d'objet et on en attend au moins un
136 # on n'a qu'un objet et on en attend plus d'1
140 def verif_type(self,val=None,cr='non'):
143 Cette methode verifie que le type de l'argument val est en conformite avec celui
144 qui est declare dans la definition du mot cle simple.
145 Elle a plusieurs modes de fonctionnement liés à la valeur de cr.
146 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:
166 if not self.verif_type(val=val,cr=cr) : return 0
169 # on n'a pas de tuple ...il faut tester sur tous les types ou les valeurs possibles
170 # XXX Pourquoi into est il traité ici et pas seulement dans verif_into ???
171 if self.definition.into != None :
173 if valeur in self.definition.into :
177 self.cr.fatal("%s n'est pas une valeur autorisée" %valeur)
180 print "problème avec :",self.nom
182 for type_permis in self.definition.type:
183 if self.compare_type(valeur,type_permis) : return 1
184 # 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
186 self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
189 def verif_into(self,cr='non'):
191 Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
192 donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
193 entre val_min et val_max
195 if self.definition.into == None :
196 #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
197 if type(self.valeur)==types.TupleType :
199 for val in self.valeur :
200 if type(val)!=types.StringType and type(val)!=types.InstanceType:
201 test = test*self.isinintervalle(val,cr=cr)
205 if type(val)!=types.StringType and type(val)!=types.InstanceType:
206 return self.isinintervalle(self.valeur,cr=cr)
210 # on est dans le cas d'un ensemble discret de valeurs possibles (into)
211 if type(self.valeur) == types.TupleType :
212 for e in self.valeur:
213 if e not in self.definition.into:
215 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
218 if self.valeur == None or self.valeur not in self.definition.into:
220 self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
224 def is_complexe(self,valeur):
225 """ Retourne 1 si valeur est un complexe, 0 sinon """
226 if type(valeur) == types.StringType :
227 # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
228 #XXX Il serait peut etre plus judicieux d'appeler une méthode de self.jdc
229 #XXX qui retournerait l'objet résultat de l'évaluation
230 #XXX ou meme de faire cette evaluation a l'exterieur de cette classe ??
231 if not self.jdc :return 0
233 valeur = eval(valeur,self.jdc.g_context)
236 if type(valeur) == types.InstanceType :
237 #XXX je n'y touche pas pour ne pas tout casser mais il serait
238 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
239 if valeur.__class__.__name__ in ('EVAL','complexe'):
241 elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
242 # il faut tester si la valeur du parametre est un entier
243 #XXX ne serait ce pas plutot complexe ???? sinon expliquer
244 return self.is_entier(valeur.valeur)
246 print "Objet non reconnu dans is_complexe %s" %`valeur`
248 # Pour permettre l'utilisation de complexes Python
249 #elif type(valeur) == types.ComplexType:
251 elif type(valeur) != types.TupleType :
254 if len(valeur) != 3 :
257 if type(valeur[0]) != types.StringType : return 0
258 if string.strip(valeur[0]) not in ('RI','MP'):
261 if not self.is_reel(valeur[1]) or not self.is_reel(valeur[2]) : return 0
264 def is_reel(self,valeur):
266 Retourne 1 si valeur est un reel, 0 sinon
268 if type(valeur) == types.StringType :
269 # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
270 if not self.jdc :return 0
272 valeur = eval(valeur,self.jdc.g_context)
275 if type(valeur) == types.InstanceType :
276 #XXX je n'y touche pas pour ne pas tout casser mais il serait
277 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
278 #XXX ou valeur.is_reel()
279 #XXX ou encore valeur.compare(self.is_reel)
280 if valeur.__class__.__name__ in ('EVAL','reel') :
282 elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
283 # il faut tester si la valeur du parametre est un réel
284 return self.is_reel(valeur.valeur)
286 print "Objet non reconnu dans is_reel %s" %`valeur`
288 elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
289 # ce n'est pas un réel
294 def is_entier(self,valeur):
295 """ Retourne 1 si valeur est un entier, 0 sinon """
296 if type(valeur) == types.StringType :
297 # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
298 if not self.jdc :return 0
300 valeur = eval(valeur,self.jdc.g_context)
303 if type(valeur) == types.InstanceType :
304 #XXX je n'y touche pas pour ne pas tout casser mais il serait
305 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
306 if valeur.__class__.__name__ in ('EVAL','entier') :
308 elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
309 # il faut tester si la valeur du parametre est un entier
310 return self.is_entier(valeur.valeur)
312 print "Objet non reconnu dans is_reel %s" %`valeur`
314 elif type(valeur) not in (types.IntType,types.LongType):
315 # ce n'est pas un entier
320 def is_shell(self,valeur):
322 Retourne 1 si valeur est un shell, 0 sinon
323 Pour l'instant aucune vérification n'est faite
324 On impose juste que valeur soit une string
326 if type(valeur) != types.StringType:
331 def is_object_from(self,objet,classe):
333 Retourne 1 si valeur est un objet de la classe classe ou d'une sous-classe de classe,
336 if type(objet) != types.InstanceType :
337 if type(objet) == types.StringType:
338 if not self.jdc :return 0
340 objet = eval(objet,self.jdc.g_context)
341 if type(objet) != types.InstanceType : return 0
346 if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
351 def compare_type(self,valeur,type_permis):
353 Fonction booléenne qui retourne 1 si valeur est du type type_permis, 0 sinon
355 if type(valeur) == types.InstanceType and valeur.__class__.__name__ == 'PARAMETRE':
356 if type(valeur.valeur) == types.TupleType :
357 # on a à faire à un PARAMETRE qui définit une liste d'items
358 # --> on teste sur la première car on n'accepte que les liste homogènes
359 valeur = valeur.valeur[0]
360 if type_permis == 'R':
361 return self.is_reel(valeur)
362 elif type_permis == 'I':
363 return self.is_entier(valeur)
364 elif type_permis == 'C':
365 return self.is_complexe(valeur)
366 elif type_permis == 'shell':
367 return self.is_shell(valeur)
368 elif type_permis == 'TXM':
369 if type(valeur) != types.InstanceType:
370 return type(valeur)==types.StringType
372 #XXX je n'y touche pas pour ne pas tout casser mais il serait
373 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('TXM'), par exemple
374 if valeur.__class__.__name__ == 'chaine' :
376 elif valeur.__class__.__name__ == 'PARAMETRE':
377 # il faut tester si la valeur du parametre est une string
378 return type(valeur.valeur)==types.StringType
381 elif type(type_permis) == types.ClassType:
382 # on ne teste pas certains objets de type GEOM , assd, ...
383 # On appelle la méthode de classe is_object de type_permis.
384 # Comme valeur peut etre de n'importe quel type on utilise la fonction (is_object.im_func)
385 # et non pas la methode (is_object) ce qui risquerait de provoquer des erreurs
386 if type_permis.is_object.im_func(valeur):
389 return self.is_object_from(valeur,type_permis)
391 print "Type non encore géré %s" %`type_permis`
392 print self.nom,self.parent.nom,self.jdc.fichier
394 def isinintervalle(self,valeur,cr='non'):
396 Booléenne qui retourne 1 si la valeur passée en argument est comprise dans
397 le domaine de définition donné dans le catalogue, 0 sinon.
399 if type(valeur) not in (types.IntType,types.FloatType,types.LongType) :
402 min = self.definition.val_min
403 max = self.definition.val_max
404 if min == '**': min = valeur -1
405 if max == '**': max = valeur +1
406 if valeur < min or valeur > max :
408 self.cr.fatal(string.join(("La valeur :",`valeur`," du mot-clé ",self.nom,\
409 " est en dehors du domaine de validité [",`min`,",",`max`,"]")))
414 def init_modif_up(self):
416 Propage l'état modifié au parent s'il existe et n'est l'objet
419 if self.parent and self.parent != self :
420 self.parent.state = 'modified'
423 """ génère le rapport de validation de self """
425 self.cr.debut = "Mot-clé simple : "+self.nom
426 self.cr.fin = "Fin Mot-clé simple : "+self.nom
427 self.state = 'modified'
429 self.isvalid(cr='oui')
430 except AsException,e:
431 if CONTEXT.debug : traceback.print_exc()
432 self.cr.fatal(string.join(("Mot-clé simple : ",self.nom,str(e))))