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
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é")))
89 valid = self.verif_type(val=v,cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr)
91 # On verifie les validateurs s'il y en a
93 if self.definition.validators and not self.definition.validators.verif(self.valeur):
95 self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info())))
100 self.state = 'unchanged'
101 # Si la validité du mot clé a changé, on le signale à l'objet parent
102 if not old_valid or old_valid != self.valid :
107 """ indique si le mot-clé est obligatoire
109 return self.definition.statut=='o'
111 def verif_card(self,cr='non'):
113 un mot-clé simple ne peut etre répété :
114 la cardinalité ici s'entend par la vérification que le nombre d'arguments de self.valeur
115 est bien compris entre self.min et self.max dans le cas où il s'agit d'une liste
118 min=self.definition.min
119 max=self.definition.max
120 if type(self.valeur) in (types.ListType,types.TupleType) and 'C' not in self.definition.type :
121 if len(self.valeur) < min or len(self.valeur)>max:
123 self.cr.fatal("Nombre d'arguments %s incorrects pour %s (min = %s, max = %s)" %(`self.valeur`,self.nom,min,max))
126 if self.valeur == None :
128 # on n'a pas d'objet et on en attend au moins un
132 # on n'a qu'un objet et on en attend plus d'1
136 def verif_type(self,val=None,cr='non'):
139 Cette methode verifie que le type de l'argument val est en conformite avec celui
140 qui est declare dans la definition du mot cle simple.
141 Elle a plusieurs modes de fonctionnement liés à la valeur de cr.
142 Si cr vaut 'oui' : elle remplit le compte-rendu self.cr sinon elle ne le remplit pas.
143 PARAMETRE DE RETOUR :
144 Cette méthode retourne une valeur booléenne qui vaut 1 si le type de val est correct ou 0 sinon
150 self.cr.fatal("None n'est pas une valeur autorisée")
152 if type(valeur) == types.TupleType:
153 # on peut avoir à faire à un complexe ou une liste de valeurs ...
154 if self.is_complexe(valeur) : return 1
157 if not self.verif_type(val=val,cr=cr) : return 0
159 elif type(valeur) == types.ListType:
161 if not self.verif_type(val=val,cr=cr) : return 0
164 # on n'a pas de tuple ...il faut tester sur tous les types ou les valeurs possibles
165 # XXX Pourquoi into est il traité ici et pas seulement dans verif_into ???
166 if self.definition.into != None :
168 if valeur in self.definition.into :
172 self.cr.fatal("%s n'est pas une valeur autorisée" %valeur)
175 print "problème avec :",self.nom
176 print 'valeur =',valeur
178 for type_permis in self.definition.type:
179 if self.compare_type(valeur,type_permis) : return 1
180 # 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
182 self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
185 def verif_into(self,cr='non'):
187 Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
188 donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
189 entre val_min et val_max
191 if self.definition.into == None :
192 #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
193 if type(self.valeur)==types.TupleType :
195 for val in self.valeur :
196 if type(val)!=types.StringType and type(val)!=types.InstanceType:
197 test = test*self.isinintervalle(val,cr=cr)
201 if type(val)!=types.StringType and type(val)!=types.InstanceType:
202 return self.isinintervalle(self.valeur,cr=cr)
206 # on est dans le cas d'un ensemble discret de valeurs possibles (into)
207 if type(self.valeur) == types.TupleType :
208 for e in self.valeur:
209 if e not in self.definition.into:
211 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
214 if self.valeur == None or self.valeur not in self.definition.into:
216 self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
220 def is_complexe(self,valeur):
221 """ Retourne 1 si valeur est un complexe, 0 sinon """
222 if type(valeur) == types.StringType :
223 # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
224 #XXX Il serait peut etre plus judicieux d'appeler une méthode de self.jdc
225 #XXX qui retournerait l'objet résultat de l'évaluation
226 #XXX ou meme de faire cette evaluation a l'exterieur de cette classe ??
227 if not self.jdc :return 0
229 valeur = eval(valeur,self.jdc.g_context)
232 if type(valeur) == types.InstanceType :
233 #XXX je n'y touche pas pour ne pas tout casser mais il serait
234 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
235 if valeur.__class__.__name__ in ('EVAL','complexe'):
237 elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
238 # il faut tester si la valeur du parametre est un entier
239 #XXX ne serait ce pas plutot complexe ???? sinon expliquer
240 return self.is_entier(valeur.valeur)
242 print "Objet non reconnu dans is_complexe %s" %`valeur`
244 # Pour permettre l'utilisation de complexes Python
245 #elif type(valeur) == types.ComplexType:
247 elif type(valeur) != types.TupleType :
250 if len(valeur) != 3 :
253 if type(valeur[0]) != types.StringType : return 0
254 if string.strip(valeur[0]) not in ('RI','MP'):
257 if not self.is_reel(valeur[1]) or not self.is_reel(valeur[2]) : return 0
260 def is_reel(self,valeur):
262 Retourne 1 si valeur est un reel, 0 sinon
264 if type(valeur) == types.StringType :
265 # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
266 if not self.jdc :return 0
268 valeur = eval(valeur,self.jdc.g_context)
271 if type(valeur) == types.InstanceType :
272 #XXX je n'y touche pas pour ne pas tout casser mais il serait
273 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
274 #XXX ou valeur.is_reel()
275 #XXX ou encore valeur.compare(self.is_reel)
276 if valeur.__class__.__name__ in ('EVAL','reel') :
278 elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
279 # il faut tester si la valeur du parametre est un réel
280 return self.is_reel(valeur.valeur)
282 print "Objet non reconnu dans is_reel %s" %`valeur`
284 elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
285 # ce n'est pas un réel
290 def is_entier(self,valeur):
291 """ Retourne 1 si valeur est un entier, 0 sinon """
292 if type(valeur) == types.StringType :
293 # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
294 if not self.jdc :return 0
296 valeur = eval(valeur,self.jdc.g_context)
299 if type(valeur) == types.InstanceType :
300 #XXX je n'y touche pas pour ne pas tout casser mais il serait
301 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
302 if valeur.__class__.__name__ in ('EVAL','entier') :
304 elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
305 # il faut tester si la valeur du parametre est un entier
306 return self.is_entier(valeur.valeur)
308 print "Objet non reconnu dans is_reel %s" %`valeur`
310 elif type(valeur) not in (types.IntType,types.LongType):
311 # ce n'est pas un entier
316 def is_shell(self,valeur):
318 Retourne 1 si valeur est un shell, 0 sinon
319 Pour l'instant aucune vérification n'est faite
320 On impose juste que valeur soit une string
322 if type(valeur) != types.StringType:
327 def is_object_from(self,objet,classe):
329 Retourne 1 si valeur est un objet de la classe classe ou d'une sous-classe de classe,
332 if type(objet) != types.InstanceType :
333 if type(objet) == types.StringType:
334 if not self.jdc :return 0
336 objet = eval(objet,self.jdc.g_context)
337 if type(objet) != types.InstanceType : return 0
342 if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
347 def compare_type(self,valeur,type_permis):
349 Fonction booléenne qui retourne 1 si valeur est du type type_permis, 0 sinon
351 if type(valeur) == types.InstanceType and valeur.__class__.__name__ == 'PARAMETRE':
352 if type(valeur.valeur) == types.TupleType :
353 # on a à faire à un PARAMETRE qui définit une liste d'items
354 # --> on teste sur la première car on n'accepte que les liste homogènes
355 valeur = valeur.valeur[0]
356 if type_permis == 'R':
357 return self.is_reel(valeur)
358 elif type_permis == 'I':
359 return self.is_entier(valeur)
360 elif type_permis == 'C':
361 return self.is_complexe(valeur)
362 elif type_permis == 'shell':
363 return self.is_shell(valeur)
364 elif type_permis == 'TXM':
365 if type(valeur) != types.InstanceType:
366 return type(valeur)==types.StringType
368 #XXX je n'y touche pas pour ne pas tout casser mais il serait
369 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('TXM'), par exemple
370 if valeur.__class__.__name__ == 'chaine' :
372 elif valeur.__class__.__name__ == 'PARAMETRE':
373 # il faut tester si la valeur du parametre est une string
374 return type(valeur.valeur)==types.StringType
377 elif type(type_permis) == types.ClassType:
378 # on ne teste pas certains objets de type GEOM , assd, ...
379 # On appelle la méthode de classe is_object de type_permis.
380 # Comme valeur peut etre de n'importe quel type on utilise la fonction (is_object.im_func)
381 # et non pas la methode (is_object) ce qui risquerait de provoquer des erreurs
382 if type_permis.is_object.im_func(valeur):
385 return self.is_object_from(valeur,type_permis)
387 print "Type non encore géré %s" %`type_permis`
388 print self.nom,self.parent.nom,self.jdc.fichier
390 def isinintervalle(self,valeur,cr='non'):
392 Booléenne qui retourne 1 si la valeur passée en argument est comprise dans
393 le domaine de définition donné dans le catalogue, 0 sinon.
395 if type(valeur) not in (types.IntType,types.FloatType,types.LongType) :
398 min = self.definition.val_min
399 max = self.definition.val_max
400 if min == '**': min = valeur -1
401 if max == '**': max = valeur +1
402 if valeur < min or valeur > max :
404 self.cr.fatal(string.join(("La valeur :",`valeur`," du mot-clé ",self.nom,\
405 " est en dehors du domaine de validité [",`min`,",",`max`,"]")))
410 def init_modif_up(self):
412 Propage l'état modifié au parent s'il existe et n'est l'objet
415 if self.parent and self.parent != self :
416 self.parent.state = 'modified'
419 """ génère le rapport de validation de self """
421 self.cr.debut = "Mot-clé simple : "+self.nom
422 self.cr.fin = "Fin Mot-clé simple : "+self.nom
423 self.state = 'modified'
425 self.isvalid(cr='oui')
426 except AsException,e:
427 if CONTEXT.debug : traceback.print_exc()
428 self.cr.fatal(string.join(("Mot-clé simple : ",self.nom,str(e))))