1 #@ MODIF V_MCSIMP Validation DATE 22/02/2005 AUTEUR DURAND C.DURAND
2 # -*- coding: iso-8859-1 -*-
3 # CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
6 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
7 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
8 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
9 # (AT YOUR OPTION) ANY LATER VERSION.
11 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
12 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
13 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
14 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
16 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
17 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
18 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
21 # ======================================================================
24 Ce module contient la classe mixin MCSIMP qui porte les méthodes
25 nécessaires pour réaliser la validation d'un objet de type MCSIMP
28 Une classe mixin porte principalement des traitements et est
29 utilisée par héritage multiple pour composer les traitements.
36 from Noyau import N_CR
37 from Noyau.N_Exception import AsException
42 Cette classe est quasiment identique à la classe originale d'EFICAS
43 a part quelques changements cosmétiques et des chagements pour la
44 faire fonctionner de facon plus autonome par rapport à l'environnement
47 A mon avis, il faudrait aller plus loin et réduire les dépendances
48 amont au strict nécessaire.
50 - Est il indispensable de faire l'évaluation de la valeur dans le contexte
51 du jdc dans cette classe.
53 - Ne pourrait on pas doter les objets en présence des méthodes suffisantes
54 pour éviter les tests un peu particuliers sur GEOM, PARAMETRE et autres. J'ai
55 d'ailleurs modifié la classe pour éviter l'import de GEOM
61 self.state='undetermined'
64 if hasattr(self,'valid'):
70 def set_valid(self,valid):
71 old_valid=self.get_valid()
73 self.state = 'unchanged'
74 if not old_valid or old_valid != self.valid :
77 def isvalid(self,cr='non'):
79 Cette méthode retourne un indicateur de validité de l'objet de type MCSIMP
81 - 0 si l'objet est invalide
82 - 1 si l'objet est valide
84 Le paramètre cr permet de paramétrer le traitement. Si cr == 'oui'
85 la méthode construit également un comte-rendu de validation
86 dans self.cr qui doit avoir été créé préalablement.
88 if self.state == 'unchanged':
93 # verification presence
94 if self.isoblig() and v == None :
96 self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé")))
102 self.cr.fatal("None n'est pas une valeur autorisée")
105 valid = self.verif_type(val=v,cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr)
107 # On verifie les validateurs s'il y en a et si necessaire (valid == 1)
109 if valid and self.definition.validators and not self.definition.validators.verif(self.valeur):
111 self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info())))
113 # fin des validateurs
116 self.set_valid(valid)
120 """ indique si le mot-clé est obligatoire
122 return self.definition.statut=='o'
124 def verif_card(self,cr='non'):
126 un mot-clé simple ne peut etre répété :
127 la cardinalité ici s'entend par la vérification que le nombre d'arguments de self.valeur
128 est bien compris entre self.min et self.max dans le cas où il s'agit d'une liste
131 min=self.definition.min
132 max=self.definition.max
134 if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
135 length=len(self.valeur)
137 if self.valeur == None :
142 if length < min or length >max:
144 self.cr.fatal("Nombre d'arguments de %s incorrect pour %s (min = %s, max = %s)" %(`self.valeur`,self.nom,min,max))
148 def verif_type(self,val=None,cr='non'):
151 Cette methode verifie que le type de l'argument val est en conformite avec celui
152 qui est declare dans la definition du mot cle simple.
153 Elle a plusieurs modes de fonctionnement liés à la valeur de cr.
154 Si cr vaut 'oui' : elle remplit le compte-rendu self.cr sinon elle ne le remplit pas.
155 PARAMETRE DE RETOUR :
156 Cette méthode retourne une valeur booléenne qui vaut 1 si le type de val est correct ou 0 sinon
162 self.cr.fatal("None n'est pas une valeur autorisée")
165 if type(valeur) == types.TupleType and not valeur[0] in ('RI','MP') or type(valeur) == types.ListType:
166 # Ici on a identifié une liste de valeurs
168 if not self.verif_type(val=val,cr=cr) : return 0
171 # Ici, valeur est un scalaire ...il faut tester sur tous les types ou les valeurs possibles
173 for type_permis in self.definition.type:
174 if self.compare_type(valeur,type_permis) : return 1
176 # 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
178 self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
181 def verif_into(self,cr='non'):
183 Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
184 donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
185 entre val_min et val_max
187 if self.definition.into == None :
188 #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
189 if self.definition.val_min == '**' and self.definition.val_max == '**':
190 # L'intervalle est infini, on ne fait pas de test
192 if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
193 # Cas d'une liste de valeurs
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)
202 if type(val)!=types.StringType and type(val)!=types.InstanceType:
203 return self.isinintervalle(self.valeur,cr=cr)
207 # on est dans le cas d'un ensemble discret de valeurs possibles (into)
208 if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
209 # Cas d'une liste de valeur
210 for e in self.valeur:
211 if e not in self.definition.into:
213 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
216 if self.valeur not in self.definition.into:
218 self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
222 def is_complexe(self,valeur):
223 """ Retourne 1 si valeur est un complexe, 0 sinon """
224 if type(valeur) == types.InstanceType :
225 #XXX je n'y touche pas pour ne pas tout casser mais il serait
226 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
227 if valeur.__class__.__name__ in ('complexe','PARAMETRE_EVAL'):
229 elif valeur.__class__.__name__ in ('PARAMETRE',):
230 # il faut tester si la valeur du parametre est un complexe
231 return self.is_complexe(valeur.valeur)
234 # Pour permettre l'utilisation de complexes Python
235 #elif type(valeur) == types.ComplexType:
237 elif type(valeur) != types.TupleType :
238 # On n'autorise pas les listes pour les complexes
240 elif len(valeur) != 3:return 0
242 # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
243 # valeur suivie de 2 reels.
245 if string.strip(valeur[0]) in ('RI','MP') and self.is_reel(valeur[1]) and self.is_reel(valeur[2]):
250 def is_reel(self,valeur):
252 Retourne 1 si valeur est un reel, 0 sinon
254 if type(valeur) == types.InstanceType :
255 #XXX je n'y touche pas pour ne pas tout casser mais il serait
256 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
257 #XXX ou valeur.is_reel()
258 #XXX ou encore valeur.compare(self.is_reel)
259 if valeur.__class__.__name__ in ('reel','PARAMETRE_EVAL') :
261 elif valeur.__class__.__name__ in ('PARAMETRE',):
262 # il faut tester si la valeur du parametre est un réel
263 return self.is_reel(valeur.valeur)
266 elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
267 # ce n'est pas un réel
272 def is_entier(self,valeur):
273 """ Retourne 1 si valeur est un entier, 0 sinon """
274 if type(valeur) == types.InstanceType :
275 #XXX je n'y touche pas pour ne pas tout casser mais il serait
276 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
277 if valeur.__class__.__name__ in ('entier','PARAMETRE_EVAL') :
279 elif valeur.__class__.__name__ in ('PARAMETRE',):
280 # il faut tester si la valeur du parametre est un entier
281 return self.is_entier(valeur.valeur)
284 elif type(valeur) not in (types.IntType,types.LongType):
285 # ce n'est pas un entier
290 def is_shell(self,valeur):
292 Retourne 1 si valeur est un shell, 0 sinon
293 Pour l'instant aucune vérification n'est faite
294 On impose juste que valeur soit une string
296 if type(valeur) != types.StringType:
301 def is_object_from(self,objet,classe):
303 Retourne 1 si objet est une instance de la classe classe, 0 sinon
305 if type(objet) != types.InstanceType :
308 if isinstance(objet,classe) :
309 # On accepte les instances de la classe et des classes derivees
314 def compare_type(self,valeur,type_permis):
316 Fonction booléenne qui retourne 1 si valeur est du type type_permis, 0 sinon
318 if type(valeur) == types.InstanceType and valeur.__class__.__name__ == 'PARAMETRE':
319 if type(valeur.valeur) == types.TupleType :
320 # on a à faire à un PARAMETRE qui définit une liste d'items
321 # --> on teste sur la première car on n'accepte que les liste homogènes
322 valeur = valeur.valeur[0]
323 if type_permis == 'R':
324 return self.is_reel(valeur)
325 elif type_permis == 'I':
326 return self.is_entier(valeur)
327 elif type_permis == 'C':
328 return self.is_complexe(valeur)
329 elif type_permis == 'shell':
330 return self.is_shell(valeur)
331 elif type_permis == 'TXM':
332 if type(valeur) != types.InstanceType:
333 return type(valeur)==types.StringType
335 #XXX je n'y touche pas pour ne pas tout casser mais il serait
336 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('TXM'), par exemple
337 if valeur.__class__.__name__ == 'chaine' :
339 elif valeur.__class__.__name__ == 'PARAMETRE':
340 # il faut tester si la valeur du parametre est une string
341 return type(valeur.valeur)==types.StringType
344 elif type(type_permis) == types.ClassType:
345 # on ne teste pas certains objets de type GEOM , assd, ...
346 # On appelle la méthode de classe is_object de type_permis.
347 # Comme valeur peut etre de n'importe quel type on utilise la fonction (is_object.im_func)
348 # et non pas la methode (is_object) ce qui risquerait de provoquer des erreurs
349 if type_permis.is_object.im_func(valeur):
352 return self.is_object_from(valeur,type_permis)
354 print "Type non encore géré %s" %`type_permis`
355 print self.nom,self.parent.nom,self.jdc.fichier
357 def isinintervalle(self,valeur,cr='non'):
359 Booléenne qui retourne 1 si la valeur passée en argument est comprise dans
360 le domaine de définition donné dans le catalogue, 0 sinon.
362 if type(valeur) not in (types.IntType,types.FloatType,types.LongType) :
365 min = self.definition.val_min
366 max = self.definition.val_max
367 if min == '**': min = valeur -1
368 if max == '**': max = valeur +1
369 if valeur < min or valeur > max :
371 self.cr.fatal(string.join(("La valeur :",`valeur`," du mot-clé ",self.nom,\
372 " est en dehors du domaine de validité [",`min`,",",`max`,"]")))
377 def init_modif_up(self):
379 Propage l'état modifié au parent s'il existe et n'est l'objet
382 if self.parent and self.parent != self :
383 self.parent.state = 'modified'
386 """ génère le rapport de validation de self """
388 self.cr.debut = "Mot-clé simple : "+self.nom
389 self.cr.fin = "Fin Mot-clé simple : "+self.nom
390 self.state = 'modified'
392 self.isvalid(cr='oui')
393 except AsException,e:
394 if CONTEXT.debug : traceback.print_exc()
395 self.cr.fatal(string.join(("Mot-clé simple : ",self.nom,str(e))))