Salome HOME
CCAR: modification de la procedure d'installation : install.py et de
[tools/eficas.git] / Validation / V_MCSIMP.py
1 """
2    Ce module contient la classe mixin MCSIMP qui porte les méthodes
3    nécessaires pour réaliser la validation d'un objet de type MCSIMP
4    dérivé de OBJECT.
5
6    Une classe mixin porte principalement des traitements et est
7    utilisée par héritage multiple pour composer les traitements.
8 """
9 # Modules Python
10 import string,types
11 import traceback
12
13 # Modules EFICAS
14 from Noyau import N_CR
15 from Noyau.N_Exception import AsException
16
17 class MCSIMP:
18    """
19       COMMENTAIRE CCAR
20         Cette classe est quasiment identique à la classe originale d'EFICAS
21         a part quelques changements cosmétiques et des chagements pour la
22         faire fonctionner de facon plus autonome par rapport à l'environnement
23         EFICAS
24  
25         A mon avis, il faudrait aller plus loin et réduire les dépendances
26         amont au strict nécessaire.
27
28         - Est il indispensable de faire l'évaluation de la valeur dans le contexte
29           du jdc dans cette classe.
30
31         - Ne pourrait on pas doter les objets en présence des méthodes suffisantes
32           pour éviter les tests un peu particuliers sur GEOM, PARAMETRE et autres. J'ai
33           d'ailleurs modifié la classe pour éviter l'import de GEOM
34    """
35
36    CR=N_CR.CR
37    
38    def __init__(self):
39       self.state='undetermined'
40
41    def isvalid(self,cr='non'):
42       """
43          Cette méthode retourne un indicateur de validité de l'objet
44          de type MCSIMP 
45          
46          - 0 si l'objet est invalide
47  
48          - 1 si l'objet est valide
49
50          Le pramètre cr permet de paramétrer le traitement. Si cr == 'oui'
51          la méthode construit également un comte-rendu de validation
52          dans self.cr qui doit avoir été créé préalablement.
53       """
54       if self.state == 'unchanged':
55         return self.valid
56       else:
57         valid = 1
58         if hasattr(self,'valid'):
59           old_valid = self.valid
60         else:
61           old_valid = None
62         v=self.valeur
63         #  presence
64         if self.isoblig() and v == None :
65           if cr == 'oui' :
66             self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé")))
67           valid = 0
68         # type,into ...
69         valid = self.verif_type(cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr)
70         self.valid = valid
71         self.state = 'unchanged'
72         # Si la validité du mot clé a changé, on le signale à l'objet parent
73         if old_valid:
74           if old_valid != self.valid : self.init_modif_up()
75         return self.valid
76
77    def isoblig(self):
78       """ indique si le mot-clé est obligatoire
79       """
80       return self.definition.statut=='o'
81
82    def verif_card(self,cr='non'):
83       """ 
84          un mot-clé simple ne peut être répété :
85            la cardinalité ici s'entend par la vérification que le nombre d'arguments de self.valeur
86            est bien compris entre self.min et self.max dans le cas où il s'agit d'une liste
87       """
88       card = 1
89       min=self.definition.min
90       max=self.definition.max
91       if type(self.valeur) in (types.ListType,types.TupleType) and 'C' not in self.definition.type :
92         if len(self.valeur) < min or len(self.valeur)>max:
93           if cr == 'oui':
94             self.cr.fatal("Nombre d'arguments %s incorrects pour %s (min = %s, max = %s)" %(`self.valeur`,self.nom,min,max))
95           card = 0
96       else:
97         if self.valeur == None :
98           if min >= 1 :
99             # on n'a pas d'objet et on en attend au moins un
100             card=0
101         else :
102           if min > 1:
103             # on n'a qu'un objet et on en attend plus d'1
104             card = 0
105       return card
106
107    def verif_type(self,val=None,cr='non'):
108       """
109         FONCTION :
110          Cette méthode a plusieurs modes de fonctionnement liés à la valeur de val et de cr.
111          Si cr ne vaut pas 'oui' : elle ne remplit pas le compte-rendu self.cr
112          Si val vaut None, elle vérifie le type de self.valeur
113          Si val ne vaut pas None, elle vérifie le type de val
114         PARAMETRE DE RETOUR :
115          Cette méthode retourne une valeur booléenne qui vaut 1 si le type est correct ou 0 sinon
116          
117       """
118       if val != None:
119         valeur = val
120       else:
121         valeur = self.valeur
122       if valeur == None :
123         if cr == 'oui':
124           self.cr.fatal("None n'est pas une valeur autorisée")
125         return 0
126       if type(valeur) == types.TupleType:
127         # on peut avoir à faire à un complexe ou une liste de valeurs ...
128         if self.is_complexe(valeur) : return 1
129         else:
130           for val in valeur:
131             if not self.verif_type(val=val,cr=cr) : return 0
132           return 1
133       elif type(valeur) == types.ListType:
134         for val in valeur:
135             if not self.verif_type(val=val,cr=cr) : return 0
136         return 1
137       else:
138         # on n'a pas de tuple ...il faut tester sur tous les types ou les valeurs possibles
139         # XXX Pourquoi into est il traité ici et pas seulement dans verif_into ???
140         if self.definition.into != None :
141           try:
142             if valeur in self.definition.into :
143               return 1
144             else:
145               if cr == 'oui':
146                 self.cr.fatal("%s n'est pas une valeur autorisée" %valeur)
147               return 0
148           except:
149             print "problème avec :",self.nom
150             print 'valeur =',valeur
151             return 0
152         for type_permis in self.definition.type:
153           if self.compare_type(valeur,type_permis) : return 1
154         # 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
155         if cr =='oui':
156           self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
157         return 0
158
159    def verif_into(self,cr='non'):
160       """
161       Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
162       donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
163       entre val_min et val_max
164       """
165       if self.definition.into == None :
166         #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
167         if type(self.valeur)==types.TupleType :
168           test = 1
169           for val in self.valeur :
170             if type(val)!=types.StringType and type(val)!=types.InstanceType:
171               test = test*self.isinintervalle(val,cr=cr)
172           return test
173         else :
174           val = self.valeur
175           if type(val)!=types.StringType and type(val)!=types.InstanceType:
176             return self.isinintervalle(self.valeur,cr=cr)
177           else :
178             return 1
179       else :
180         # on est dans le cas d'un ensemble discret de valeurs possibles (into)
181         if type(self.valeur) == types.TupleType :
182           for e in self.valeur:
183             if e not in self.definition.into:
184               if cr=='oui':
185                 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
186               return 0
187         else:
188           if self.valeur == None or self.valeur not in self.definition.into:
189             if cr=='oui':
190               self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
191             return 0
192         return 1
193
194    def is_complexe(self,valeur):
195       """ Retourne 1 si valeur est un complexe, 0 sinon """
196       if type(valeur) == types.StringType :
197         # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
198         #XXX Il serait peut etre plus judicieux d'appeler une méthode de self.jdc
199         #XXX qui retournerait l'objet résultat de l'évaluation
200         #XXX ou meme de faire cette evaluation a l'exterieur de cette classe ??
201         if not self.jdc :return 0
202         try :
203           valeur = eval(valeur,self.jdc.g_context)
204         except:
205           return 0
206       if type(valeur) == types.InstanceType :
207         #XXX je n'y touche pas pour ne pas tout casser mais il serait
208         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
209         if valeur.__class__.__name__ in ('EVAL','complexe'):
210           return 1
211         elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
212           # il faut tester si la valeur du parametre est un entier
213           #XXX ne serait ce pas plutot complexe ???? sinon expliquer
214           return self.is_entier(valeur.valeur)
215         else:
216           print "Objet non reconnu dans is_complexe %s" %`valeur`
217           return 0
218       elif type(valeur) != types.TupleType :
219         return 0
220       else:
221         if len(valeur) != 3 :
222           return 0
223         else:
224           if type(valeur[0]) != types.StringType : return 0
225           if string.strip(valeur[0]) not in ('RI','MP'):
226             return 0
227           else:
228             if not self.is_reel(valeur[1]) or not self.is_reel(valeur[2]) : return 0
229             else: return 1
230
231    def is_reel(self,valeur):
232       """
233       Retourne 1 si valeur est un reel, 0 sinon
234       """
235       if type(valeur) == types.StringType :
236         # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
237         if not self.jdc :return 0
238         try :
239           valeur = eval(valeur,self.jdc.g_context)
240         except:
241           return 0
242       if type(valeur) == types.InstanceType :
243         #XXX je n'y touche pas pour ne pas tout casser mais il serait
244         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
245         #XXX ou valeur.is_reel()
246         #XXX ou encore valeur.compare(self.is_reel)
247         if valeur.__class__.__name__ in ('EVAL','reel') :
248           return 1
249         elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
250           # il faut tester si la valeur du parametre est un réel
251           return self.is_reel(valeur.valeur)
252         else:
253           print "Objet non reconnu dans is_reel %s" %`valeur`
254           return 0
255       elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
256         # ce n'est pas un réel
257         return 0
258       else:
259         return 1
260
261    def is_entier(self,valeur):
262       """ Retourne 1 si valeur est un entier, 0 sinon """
263       if type(valeur) == types.StringType :
264         # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
265         if not self.jdc :return 0
266         try :
267           valeur = eval(valeur,self.jdc.g_context)
268         except:
269           return 0
270       if type(valeur) == types.InstanceType :
271         #XXX je n'y touche pas pour ne pas tout casser mais il serait
272         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
273         if valeur.__class__.__name__ in ('EVAL','entier') :
274           return 1
275         elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
276           # il faut tester si la valeur du parametre est un entier
277           return self.is_entier(valeur.valeur)
278         else:
279           print "Objet non reconnu dans is_reel %s" %`valeur`
280           return 0
281       elif type(valeur) not in (types.IntType,types.LongType):
282         # ce n'est pas un entier
283         return 0
284       else:
285         return 1
286         
287    def is_shell(self,valeur):
288       """ 
289           Retourne 1 si valeur est un shell, 0 sinon
290           Pour l'instant aucune vérification n'est faite
291           On impose juste que valeur soit une string
292       """
293       if type(valeur) != types.StringType:
294         return 0
295       else:
296         return 1
297
298    def is_object_from(self,objet,classe):
299       """ 
300            Retourne 1 si valeur est un objet de la classe classe ou d'une sous-classe de classe,
301            0 sinon 
302       """
303       if type(objet) != types.InstanceType :
304         if type(objet) == types.StringType:
305           if not self.jdc :return 0
306           try :
307             objet = eval(objet,self.jdc.g_context)
308             if type(objet) != types.InstanceType : return 0
309           except:
310             return 0
311         else:
312           return 0
313       if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
314         return 0
315       else:
316         return 1
317
318    def compare_type(self,valeur,type_permis):
319       """
320           Fonction booléenne qui retourne 1 si valeur est du type type_permis, 0 sinon
321       """
322       if type(valeur) == types.InstanceType and valeur.__class__.__name__ == 'PARAMETRE':
323         if type(valeur.valeur) == types.TupleType :
324           # on a à faire à un PARAMETRE qui définit une liste d'items
325           # --> on teste sur la première car on n'accepte que les liste homogènes
326           valeur = valeur.valeur[0]
327       if type_permis == 'R':
328         return self.is_reel(valeur)
329       elif type_permis == 'I':
330         return self.is_entier(valeur)
331       elif type_permis == 'C':
332         return self.is_complexe(valeur)
333       elif type_permis == 'shell':
334         return self.is_shell(valeur)
335       elif type_permis == 'TXM':
336         if type(valeur) != types.InstanceType:
337           return type(valeur)==types.StringType
338         else:
339           #XXX je n'y touche pas pour ne pas tout casser mais il serait
340           #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('TXM'), par exemple
341           if valeur.__class__.__name__ == 'chaine' :
342             return 1
343           elif valeur.__class__.__name__ == 'PARAMETRE':
344             # il faut tester si la valeur du parametre est une string
345             return type(valeur.valeur)==types.StringType
346           else:
347             return 0
348       elif type(type_permis) == types.ClassType:
349         # on ne teste pas certains objets de type GEOM , assd, ...
350         # On appelle la méthode de classe is_object de type_permis.
351         # Comme valeur peut etre de n'importe quel type on utilise la fonction (is_object.im_func)
352         # et non pas la methode (is_object) ce qui risquerait de provoquer des erreurs
353         if type_permis.is_object.im_func(valeur):
354           return 1
355         else :
356           return self.is_object_from(valeur,type_permis)
357       else:
358         print "Type non encore géré %s" %`type_permis`
359         print self.nom,self.parent.nom,self.jdc.fichier
360
361    def isinintervalle(self,valeur,cr='non'):
362       """
363       Booléenne qui retourne 1 si la valeur passée en argument est comprise dans
364       le domaine de définition donné dans le catalogue, 0 sinon.
365       """
366       if type(valeur) not in (types.IntType,types.FloatType,types.LongType) :
367         return 1
368       else :
369         min = self.definition.val_min
370         max = self.definition.val_max
371         if min == '**': min = valeur -1
372         if max == '**': max = valeur +1
373         if valeur < min or valeur > max :
374           if cr=='oui':
375             self.cr.fatal(string.join(("La valeur :",`valeur`," du mot-clé ",self.nom,\
376                                        " est en dehors du domaine de validité [",`min`,",",`max`,"]")))
377           return 0
378         else :
379           return 1
380
381    def init_modif_up(self):
382       """
383          Propage l'état modifié au parent s'il existe et n'est l'objet 
384          lui-meme
385       """
386       if self.parent and self.parent != self :
387         self.parent.state = 'modified'
388
389    def report(self):
390       """ génère le rapport de validation de self """
391       self.cr=self.CR()
392       self.cr.debut = "Mot-clé simple : "+self.nom
393       self.cr.fin = "Fin Mot-clé simple : "+self.nom
394       self.state = 'modified'
395       try:
396         self.isvalid(cr='oui')
397       except AsException,e:
398         if CONTEXT.debug : traceback.print_exc()
399         self.cr.fatal(string.join(("Mot-clé simple : ",self.nom,str(e))))
400       return self.cr
401
402
403
404
405
406