2 Ce module contient des classes permettant de définir des validateurs
3 pour EFICAS. Ces classes constituent un complément à des classes existantes
4 dans Noyau/N_VALIDATOR.py ou de nouvelles classes de validation.
5 Ces classes complémentaires ne servent que pour l'IHM d'EFICAS.
6 Elles servent essentiellement à ajouter des comportements spécifiques
7 IHM aux classes existantes dans le Noyau.
8 Ces comportements pourront etre rapatries dans le Noyau quand leur
9 interface sera stabilisée.
13 import Noyau.N_VALIDATOR
17 Cette classe est la classe mere de toutes les classes complémentaires
18 que l'on trouve dans Ihm.
19 Elle porte les comportements par défaut des méthodes des validateurs.
22 def info_erreur_item(self):
24 Cette méthode permet d'avoir un message d'erreur pour un item
25 dans une liste dans le cas ou le validateur fait des vérifications
26 sur les items d'une liste. Si le validateur fait des vérifications
27 sur la liste elle meme et non sur ses items, la méthode
28 doit retourner une chaine vide.
34 Cette methode retourne une chaine de caractère qui permet à EFICAS de construire
35 un message d'aide en ligne
36 En général, le message retourné est le meme que celui retourné par la
41 def info_erreur_liste(self):
43 Cette méthode a un comportement complémentaire de celui de info_erreur_item.
44 Elle retourne un message d'erreur lié uniquement aux vérifications sur la liste
45 elle meme et pas sur ses items. Dans le cas où le validateur ne fait pas de vérification
46 sur des listes, elle retourne une chaine vide
52 Cette méthode retourne un entier qui indique si le validateur permet les listes (valeur 1)
53 ou ne les permet pas (valeur 0).
54 Par défaut, un validateur n'autorise que des scalaires.
60 Cette méthode retourne un entier qui indique si le validateur propose une liste de choix (valeur 1)
62 Par défaut, un validateur n'en propose pas.
66 def valide_liste_partielle(self,liste_courante):
69 def verif_item(self,valeur):
71 La methode verif du validateur effectue une validation complete de la valeur.
72 valeur peut etre un scalaire ou une liste. Le validateur doit traiter les 2
73 aspects s'il accepte des listes (dans ce cas la methode is_list doit retourner 1).
74 La methode valid_item sert pour effectuer des validations partielles de liste
75 Elle doit uniquement verifier la validite d'un item de liste mais pas les caracteristiques
80 def get_into(self,liste_courante=None,into_courant=None):
82 Cette méthode retourne la liste de choix proposée par le validateur. Si le validateur ne propose
83 pas de liste de choix, la méthode retourne None.
84 L'argument d'entrée liste_courante, s'il est différent de None, donne la liste des choix déjà
85 effectués par l'utilisateur. Dans ce cas, la méthode get_into doit calculer la liste des choix
86 en en tenant compte. Par exemple, si le validateur n'autorise pas les répétitions, la liste des
87 choix retournée ne doit pas contenir les choix déjà contenus dans liste_courante.
88 L'argument d'entrée into_courant, s'il est différent de None, donne la liste des choix proposés
89 par d'autres validateurs. Dans ce cas, la méthode get_into doit calculer la liste des choix à retourner
90 en se limitant à cette liste initiale. Par exemple, si into_courant vaut (1,2,3) et que le validateur
91 propose la liste de choix (3,4,5), la méthode ne doit retourner que (3,).
93 La méthode get_into peut retourner une liste vide [], ce qui veut dire qu'il n'y a pas (ou plus) de choix possible
94 Cette situation peut etre normale : l''utilisateur a utilisé tous les choix, ou résulter d'une incohérence
95 des validateurs : choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de faire la différence entre
100 def is_eval(self,valeur):
102 Cette méthode indique si valeur est un objet de type EVAL ou autre
103 que l'on ne cherchera pas à evaluer et qui doit etre considere comme toujours valide
104 Si c'est un objet de ce type elle retourne la valeur 1 sinon la valeur 0
106 if type(valeur) == types.InstanceType :
107 if valeur.__class__.__name__ in ('EVAL','entier','reel','chaine','complexe','liste','PARAMETRE_EVAL') :
111 def is_param(self,valeur):
113 Cette méthode indique si valeur est un objet de type PARAMETRE
114 dont on cherchera à evaluer la valeur (valeur.valeur)
116 if type(valeur) == types.InstanceType :
117 if valeur.__class__.__name__ in ('PARAMETRE',):
121 def is_unknown(self,valeur):
123 Cette méthode indique si valeur est un objet de type inconnu
124 c'est à dire ni de type EVAL ni de type PARAMETRE
126 if type(valeur) == types.InstanceType :
127 if not self.is_eval(valeur) and not self.is_param(valeur):
131 def surcharge_verif(self,methode_verif_initiale,valeur):
132 if type(valeur) == types.InstanceType :
133 #CCAR: pour le moment on fait comme dans is_entier de V_MCSIMP.py
134 # mais il serait préférable d'appeler une méthode de valeur : valeur.AsType()
135 # qui donnerait le type générique de l'objet.
136 # Pour un objet de "type" entier on obtiendrait par exemple 'I'
137 if valeur.__class__.__name__ in ('EVAL','entier','reel','chaine','complexe','liste','PARAMETRE_EVAL') :
138 # On ne vérifie pas le type d'un EVAL ou d'un objet de classe entier, .... C'est toujours valide
140 elif valeur.__class__.__name__ in ('PARAMETRE',):
141 # Dans le cas d'un parametre, il faut tester si la valeur du parametre est un entier
144 # Objet inconnu : invalide
145 print "Objet non reconnu dans surcharge_verif : %s" %`valeur`
148 return methode_verif_initiale(self,valeur)
150 class FunctionVal(Valid):pass
153 def verif_item(self,valeur):
154 for validator in self.validators:
155 v=validator.verif_item(valeur)
160 def info_erreur_item(self):
163 for v in self.validators:
164 if v.info_erreur_item() != "" :
166 chaine=v.info_erreur_item()
169 chaine=chaine+" \n ou "+ v.info_erreur_item()
172 def info_erreur_liste(self):
175 for v in self.validators:
176 if v.info_erreur_liste() != "" :
178 chaine=v.info_erreur_liste()
181 chaine=chaine+" \n ou "+v.info_erreur_liste()
185 Si plusieurs validateurs sont reliés par un OU
186 il suffit qu'un seul des validateurs attende une liste
187 pour qu'on considère que leur union attende une liste.
189 for validator in self.validators:
190 v=validator.is_list()
197 Dans le cas ou plusieurs validateurs sont reliés par un OU
198 il faut que tous les validateurs proposent un choix pour
199 qu'on considère que leur union propose un choix.
200 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
201 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
203 for validator in self.validators:
204 v=validator.has_into()
209 def get_into(self,liste_courante=None,into_courant=None):
211 Dans le cas ou plusieurs validateurs sont reliés par un OU
212 tous les validateurs doivent proposer un choix pour
213 qu'on considère que leur union propose un choix.
214 Tous les choix proposés par les validateurs sont réunis (opérateur d'union)
215 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
216 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
219 for validator in self.validators:
220 v_into=validator.get_into(liste_courante,into_courant)
223 validator_into.extend(v_into)
224 return validator_into
229 return "\n et ".join([v.info() for v in self.validators])
231 def info_erreur_item(self):
234 for v in self.validators:
235 if v.info_erreur_item() != "" :
237 chaine=v.info_erreur_item()
240 chaine=chaine+" \n et "+v.info_erreur_item()
243 def info_erreur_liste(self):
245 for v in self.validators:
246 if v.info_erreur_liste() != "" :
248 chaine=v.info_erreur_liste()
251 chaine=chaine+" \n et "+v.info_erreur_liste()
254 def verif_item(self,valeur):
255 for validator in self.validators:
256 v=validator.verif_item(valeur)
258 # L'info n'est probablement pas la meme que pour verif ???
259 self.local_info=validator.info()
265 Si plusieurs validateurs sont reliés par un ET
266 il faut que tous les validateurs attendent une liste
267 pour qu'on considère que leur intersection attende une liste.
268 Exemple Range(2,5) ET Card(1) n'attend pas une liste
269 Range(2,5) ET Pair attend une liste
271 for validator in self.validators:
272 v=validator.is_list()
279 Dans le cas ou plusieurs validateurs sont reliés par un ET
280 il suffit qu'un seul validateur propose un choix pour
281 qu'on considère que leur intersection propose un choix.
282 Exemple : Enum(1,2,3) ET entier pair, propose un choix
283 En revanche, entier pair ET superieur à 10 ne propose pas de choix
285 for validator in self.validators:
286 v=validator.has_into()
292 def get_into(self,liste_courante=None,into_courant=None):
294 Dans le cas ou plusieurs validateurs sont reliés par un ET
295 il suffit qu'un seul validateur propose un choix pour
296 qu'on considère que leur intersection propose un choix.
298 Tous les choix proposés par les validateurs sont croisés (opérateur d'intersection)
299 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
300 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix
302 for validator in self.validators:
303 into_courant=validator.get_into(liste_courante,into_courant)
304 if into_courant in ([],None):
308 class CardVal(Valid):
310 return "longueur de liste comprise entre %s et %s" % (self.min,self.max)
313 if self.max == '**' or self.max > 1:
318 def verif_item(self,valeur):
321 def valide_liste_partielle(self,liste_courante=None):
324 if liste_courante != None :
325 if len(liste_courante) > self.max :
329 def get_into(self,liste_courante=None,into_courant=None):
330 if into_courant is None:
332 elif liste_courante is None:
334 elif self.max == '**':
336 elif len(liste_courante) < self.max:
341 def info_erreur_liste(self):
342 return "La cardinalité de la liste doit être comprise entre %s et %s" % (self.min,self.max)
344 class ListVal(Valid):
348 def get_into(self,liste_courante=None,into_courant=None):
350 Cette méthode get_into effectue un traitement général qui consiste
351 a filtrer la liste de choix into_courant, si elle existe, en ne conservant
352 que les valeurs valides (appel de la méthode valid)
354 if into_courant is None:
358 for e in into_courant:
360 liste_choix.append(e)
363 class EnumVal(ListVal):
364 def verif_item(self,valeur):
365 if valeur not in self.into:return 0
371 def get_into(self,liste_courante=None,into_courant=None):
372 if into_courant is None:
373 liste_choix= list(self.into)
376 for e in into_courant:
378 liste_choix.append(e)
381 def info_erreur_item(self):
382 return "La valeur n'est pas dans la liste des choix possibles"
384 class LongStr(ListVal):
385 def info_erreur_item(self):
386 return "Longueur de la chaine incorrecte"
388 def verif_item(self,valeur):
391 if valeur[0]=="'" and valeur[-1]=="'" :
394 if len(valeur) < low :return 0
395 if len(valeur) > high:return 0
398 class RangeVal(ListVal):
399 def verif_item(self,valeur):
400 if valeur < self.low :return 0
401 if valeur > self.high:return 0
404 def info_erreur_item(self) :
405 return "La valeur doit être comprise entre %s et %s" % (self.low,self.high)
407 class TypeVal(ListVal):
408 def verif_item(self,valeur):
415 class PairVal(ListVal):
417 def info_erreur_item(self):
418 return "La valeur saisie doit être paire"
420 #ATTENTION METHODE SURCHARGEE: a resorber dans une future version
421 def verif_item(self,valeur):
422 if self.is_eval(valeur):
424 elif self.is_param(valeur):
426 elif self.is_unknown(valeur):
428 return valeur % 2 == 0
430 def verif(self,valeur):
431 if self.is_param(valeur):
433 if type(valeur) in (types.ListType,types.TupleType):
435 if not self.verif_item(val):
439 return self.verif_item(valeur)
441 def verif_old(self,valeur):
442 print "Ihm.I_MCSIMP.PairVal.verif: ",valeur
443 return self.surcharge_verif(Noyau.N_VALIDATOR.PairVal.verif,valeur)
445 class InstanceVal(ListVal):
446 def verif_item(self,valeur):
447 if not isinstance(valeur,self.aClass): return 0
450 class NoRepeat(ListVal):
452 return "pas de presence de doublon dans la liste"
454 def info_erreur_liste(self):
455 return "Les doublons ne sont pas permis"
457 def verif_item(self,valeur):
460 def get_into(self,liste_courante=None,into_courant=None):
462 Methode get_into spécifique pour validateur NoRepeat
463 on retourne une liste de choix qui ne contient aucune valeur de into_courant
464 déjà contenue dans liste_courante
466 if into_courant is None:
470 for e in into_courant:
471 if e in liste_choix: continue
472 if liste_courante is not None and e in liste_courante: continue
473 liste_choix.append(e)
476 class OrdList(ListVal):
477 def verif_item(self,valeur):
480 def get_into(self,liste_courante=None,into_courant=None):
482 Methode get_into spécifique pour validateur OrdList
483 on retourne une liste de choix qui ne contient aucune valeur de into_courant
484 dont la valeur est inférieure à la dernière valeur de liste_courante, si
485 elle est différente de None.
487 if into_courant is None:
489 elif not liste_courante :
493 last_val=liste_choix[-1]
494 for e in into_courant:
495 if self.ord=='croissant' and e <= last_val:continue
496 if self.ord=='decroissant' and e >= last_val:continue
497 liste_choix.append(e)
500 def info_erreur_liste(self) :
501 return "La liste doit être en ordre "+self.ord