1 # -*- coding: utf-8 -*-
2 #@ MODIF V_MCSIMP Validation DATE 04/02/2004 AUTEUR CAMBIER S.CAMBIER
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 # ======================================================================
23 Ce module contient la classe mixin MCSIMP qui porte les méthodes
24 nécessaires pour réaliser la validation d'un objet de type MCSIMP
27 Une classe mixin porte principalement des traitements et est
28 utilisée par héritage multiple pour composer les traitements.
35 from Noyau import N_CR
36 from Noyau.N_Exception import AsException
41 Cette classe est quasiment identique à la classe originale d'EFICAS
42 a part quelques changements cosmétiques et des chagements pour la
43 faire fonctionner de facon plus autonome par rapport à l'environnement
46 A mon avis, il faudrait aller plus loin et réduire les dépendances
47 amont au strict nécessaire.
49 - Est il indispensable de faire l'évaluation de la valeur dans le contexte
50 du jdc dans cette classe.
52 - Ne pourrait on pas doter les objets en présence des méthodes suffisantes
53 pour éviter les tests un peu particuliers sur GEOM, PARAMETRE et autres. J'ai
54 d'ailleurs modifié la classe pour éviter l'import de GEOM
60 self.state='undetermined'
63 if hasattr(self,'valid'):
69 def set_valid(self,valid):
70 old_valid=self.get_valid()
72 self.state = 'unchanged'
73 if not old_valid or old_valid != self.valid :
76 def isvalid(self,cr='non'):
78 Cette méthode retourne un indicateur de validité de l'objet de type MCSIMP
80 - 0 si l'objet est invalide
81 - 1 si l'objet est valide
83 Le paramètre cr permet de paramétrer le traitement. Si cr == 'oui'
84 la méthode construit également un comte-rendu de validation
85 dans self.cr qui doit avoir été créé préalablement.
87 if self.state == 'unchanged':
92 # verification presence
93 if self.isoblig() and v == None :
95 self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé")))
101 self.cr.fatal("None n'est pas une valeur autorisée")
104 valid = self.verif_type(val=v,cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr)
106 # On verifie les validateurs s'il y en a et si necessaire (valid == 1)
108 if valid and self.definition.validators and not self.definition.validators.verif(self.valeur):
110 self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info())))
112 # fin des validateurs
115 self.set_valid(valid)
119 """ indique si le mot-clé est obligatoire
121 return self.definition.statut=='o'
123 def verif_card(self,cr='non'):
125 un mot-clé simple ne peut etre répété :
126 la cardinalité ici s'entend par la vérification que le nombre d'arguments de self.valeur
127 est bien compris entre self.min et self.max dans le cas où il s'agit d'une liste
130 min=self.definition.min
131 max=self.definition.max
133 if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
134 length=len(self.valeur)
136 if self.valeur == None :
141 if length < min or length >max:
143 self.cr.fatal("Nombre d'arguments de %s incorrect pour %s (min = %s, max = %s)" %(`self.valeur`,self.nom,min,max))
147 def verif_type(self,val=None,cr='non'):
150 Cette methode verifie que le type de l'argument val est en conformite avec celui
151 qui est declare dans la definition du mot cle simple.
152 Elle a plusieurs modes de fonctionnement liés à la valeur de cr.
153 Si cr vaut 'oui' : elle remplit le compte-rendu self.cr sinon elle ne le remplit pas.
154 PARAMETRE DE RETOUR :
155 Cette méthode retourne une valeur booléenne qui vaut 1 si le type de val est correct ou 0 sinon
161 self.cr.fatal("None n'est pas une valeur autorisée")
164 if type(valeur) == types.TupleType and not valeur[0] in ('RI','MP') or type(valeur) == types.ListType:
165 # Ici on a identifié une liste de valeurs
167 if not self.verif_type(val=val,cr=cr) : return 0
170 # Ici, valeur est un scalaire ...il faut tester sur tous les types ou les valeurs possibles
172 for type_permis in self.definition.type:
173 if self.compare_type(valeur,type_permis) : return 1
175 # si on sort de la boucle précédente par ici c'est qu'on n'a trouvé aucun type valable --> valeur refusée
176 # on essaie d evaluer si c est un parametre tordu : exemple a*b ou a et b sont definis
177 if valeur.__class__.__name__ in ('PARAMETRE_EVAL','PARAMETRE'):
180 # On crée un dictionnaire qui servira de contexte aux evaluations
181 # Ce dictionnaire sera initialisé avec les paramètres du JDC
183 for param in self.jdc.params :
184 expression = param.nom+'='+repr(param.valeur)
185 # ici on enrichit le dictionnaire d
188 obj=eval( valeur.valeur,d)
190 for type_permis in self.definition.type:
191 if self.compare_type(obj,type_permis) :
194 if CONTEXT.debug : print "e = ",str(e)
197 self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
200 def verif_into(self,cr='non'):
202 Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
203 donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
204 entre val_min et val_max
206 if self.definition.into == None :
207 #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
208 if self.definition.val_min == '**' and self.definition.val_max == '**':
209 # L'intervalle est infini, on ne fait pas de test
211 #if type(self.valeur) in (types.ListType,types.TupleType) :
212 if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
213 # Cas d'une liste de valeurs
215 for val in self.valeur :
216 if type(val) != types.StringType and type(val) != types.InstanceType:
217 test = test*self.isinintervalle(val,cr=cr)
222 if type(val)!=types.StringType and type(val)!=types.InstanceType:
223 return self.isinintervalle(self.valeur,cr=cr)
227 # on est dans le cas d'un ensemble discret de valeurs possibles (into)
228 #if type(self.valeur) in (types.ListType,types.TupleType) :
229 if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
230 # Cas d'une liste de valeur
231 for e in self.valeur:
232 if e not in self.definition.into:
234 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
237 if self.valeur not in self.definition.into:
239 self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
243 def is_complexe(self,valeur):
244 """ Retourne 1 si valeur est un complexe, 0 sinon """
245 if type(valeur) == types.InstanceType :
246 #XXX je n'y touche pas pour ne pas tout casser mais il serait
247 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
248 if valeur.__class__.__name__ in ('EVAL','complexe','PARAMETRE_EVAL'):
250 elif valeur.__class__.__name__ in ('PARAMETRE',):
251 # il faut tester si la valeur du parametre est un complexe
252 return self.is_complexe(valeur.valeur)
254 print "Objet non reconnu dans is_complexe %s" %`valeur`
256 # Pour permettre l'utilisation de complexes Python
257 #elif type(valeur) == types.ComplexType:
259 elif type(valeur) != types.TupleType :
260 # On n'autorise pas les listes pour les complexes
262 elif len(valeur) != 3:return 0
264 # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
265 # valeur suivie de 2 reels.
267 if string.strip(valeur[0]) in ('RI','MP') and self.is_reel(valeur[1]) and self.is_reel(valeur[2]):
272 def is_reel(self,valeur):
274 Retourne 1 si valeur est un reel, 0 sinon
276 if type(valeur) == types.InstanceType :
277 #XXX je n'y touche pas pour ne pas tout casser mais il serait
278 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
279 #XXX ou valeur.is_reel()
280 #XXX ou encore valeur.compare(self.is_reel)
281 if valeur.__class__.__name__ in ('EVAL','reel','PARAMETRE_EVAL') :
283 elif valeur.__class__.__name__ in ('PARAMETRE',):
284 # il faut tester si la valeur du parametre est un réel
285 return self.is_reel(valeur.valeur)
287 print "Objet non reconnu dans is_reel %s" %`valeur`
289 elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
290 # ce n'est pas un réel
295 def is_entier(self,valeur):
296 """ Retourne 1 si valeur est un entier, 0 sinon """
297 if type(valeur) == types.InstanceType :
298 #XXX je n'y touche pas pour ne pas tout casser mais il serait
299 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
300 if valeur.__class__.__name__ in ('EVAL','entier','PARAMETRE_EVAL') :
302 elif valeur.__class__.__name__ in ('PARAMETRE',):
303 # il faut tester si la valeur du parametre est un entier
304 return self.is_entier(valeur.valeur)
306 print "Objet non reconnu dans is_reel %s" %`valeur`
308 elif type(valeur) not in (types.IntType,types.LongType):
309 # ce n'est pas un entier
314 def is_shell(self,valeur):
316 Retourne 1 si valeur est un shell, 0 sinon
317 Pour l'instant aucune vérification n'est faite
318 On impose juste que valeur soit une string
320 if type(valeur) != types.StringType:
325 def is_object_from(self,objet,classe):
327 Retourne 1 si valeur est un objet de la classe classe ou d'une
328 sous-classe de classe, 0 sinon
330 if type(objet) != types.InstanceType :
332 if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
337 def compare_type(self,valeur,type_permis):
339 Fonction booléenne qui retourne 1 si valeur est du type type_permis, 0 sinon
341 if type(valeur) == types.InstanceType and valeur.__class__.__name__ == 'PARAMETRE':
342 if type(valeur.valeur) == types.TupleType :
343 # on a à faire à un PARAMETRE qui définit une liste d'items
344 # --> on teste sur la première car on n'accepte que les liste homogènes
345 valeur = valeur.valeur[0]
346 if type_permis == 'R':
347 return self.is_reel(valeur)
348 elif type_permis == 'I':
349 return self.is_entier(valeur)
350 elif type_permis == 'C':
351 return self.is_complexe(valeur)
352 elif type_permis == 'shell':
353 return self.is_shell(valeur)
354 elif type_permis == 'TXM':
355 if type(valeur) != types.InstanceType:
356 return type(valeur)==types.StringType
358 #XXX je n'y touche pas pour ne pas tout casser mais il serait
359 #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('TXM'), par exemple
360 if valeur.__class__.__name__ == 'chaine' :
362 elif valeur.__class__.__name__ == 'PARAMETRE':
363 # il faut tester si la valeur du parametre est une string
364 return type(valeur.valeur)==types.StringType
367 elif type(type_permis) == types.ClassType:
368 # on ne teste pas certains objets de type GEOM , assd, ...
369 # On appelle la méthode de classe is_object de type_permis.
370 # Comme valeur peut etre de n'importe quel type on utilise la fonction (is_object.im_func)
371 # et non pas la methode (is_object) ce qui risquerait de provoquer des erreurs
372 if type_permis.is_object.im_func(valeur):
375 return self.is_object_from(valeur,type_permis)
377 print "Type non encore géré %s" %`type_permis`
378 print self.nom,self.parent.nom,self.jdc.fichier
380 def isinintervalle(self,valeur,cr='non'):
382 Booléenne qui retourne 1 si la valeur passée en argument est comprise dans
383 le domaine de définition donné dans le catalogue, 0 sinon.
385 if type(valeur) not in (types.IntType,types.FloatType,types.LongType) :
388 min = self.definition.val_min
389 max = self.definition.val_max
390 if min == '**': min = valeur -1
391 if max == '**': max = valeur +1
392 if valeur < min or valeur > max :
394 self.cr.fatal(string.join(("La valeur :",`valeur`," du mot-clé ",self.nom,\
395 " est en dehors du domaine de validité [",`min`,",",`max`,"]")))
400 def init_modif_up(self):
402 Propage l'état modifié au parent s'il existe et n'est l'objet
405 if self.parent and self.parent != self :
406 self.parent.state = 'modified'
409 """ génère le rapport de validation de self """
411 self.cr.debut = "Mot-clé simple : "+self.nom
412 self.cr.fin = "Fin Mot-clé simple : "+self.nom
413 self.state = 'modified'
415 self.isvalid(cr='oui')
416 except AsException,e:
417 if CONTEXT.debug : traceback.print_exc()
418 self.cr.fatal(string.join(("Mot-clé simple : ",self.nom,str(e))))