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 hasattr(valeur,'__class__'):
108 if valeur.__class__.__name__ in ('EVAL','entier','reel','chaine','complexe','liste','PARAMETRE_EVAL') :
112 def is_param(self,valeur):
114 Cette méthode indique si valeur est un objet de type PARAMETRE
115 dont on cherchera à evaluer la valeur (valeur.valeur)
117 if type(valeur) == types.InstanceType :
118 if valeur.__class__.__name__ in ('PARAMETRE',):
122 def is_unknown(self,valeur):
124 Cette méthode indique si valeur est un objet de type inconnu
125 c'est à dire ni de type EVAL ni de type PARAMETRE
127 if type(valeur) == types.InstanceType :
128 if not self.is_eval(valeur) and not self.is_param(valeur):
132 def surcharge_verif(self,methode_verif_initiale,valeur):
133 if type(valeur) == types.InstanceType :
134 #CCAR: pour le moment on fait comme dans is_entier de V_MCSIMP.py
135 # mais il serait préférable d'appeler une méthode de valeur : valeur.AsType()
136 # qui donnerait le type générique de l'objet.
137 # Pour un objet de "type" entier on obtiendrait par exemple 'I'
138 if valeur.__class__.__name__ in ('EVAL','entier','reel','chaine','complexe','liste','PARAMETRE_EVAL') :
139 # On ne vérifie pas le type d'un EVAL ou d'un objet de classe entier, .... C'est toujours valide
141 elif valeur.__class__.__name__ in ('PARAMETRE',):
142 # Dans le cas d'un parametre, il faut tester si la valeur du parametre est un entier
145 # Objet inconnu : invalide
146 print "Objet non reconnu dans surcharge_verif : %s" %`valeur`
149 return methode_verif_initiale(self,valeur)
151 class FunctionVal(Valid):pass
154 def verif_item(self,valeur):
155 for validator in self.validators:
156 v=validator.verif_item(valeur)
161 def info_erreur_item(self):
164 for v in self.validators:
165 if v.info_erreur_item() != " " :
167 chaine=v.info_erreur_item()
170 chaine=chaine+" \n ou "+ v.info_erreur_item()
173 def info_erreur_liste(self):
176 for v in self.validators:
177 if v.info_erreur_liste() != " " :
179 chaine=v.info_erreur_liste()
182 chaine=chaine+" \n ou "+v.info_erreur_liste()
186 Si plusieurs validateurs sont reliés par un OU
187 il suffit qu'un seul des validateurs attende une liste
188 pour qu'on considère que leur union attende une liste.
190 for validator in self.validators:
191 v=validator.is_list()
198 Dans le cas ou plusieurs validateurs sont reliés par un OU
199 il faut que tous les validateurs proposent un choix pour
200 qu'on considère que leur union propose un choix.
201 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
202 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
204 for validator in self.validators:
205 v=validator.has_into()
210 def get_into(self,liste_courante=None,into_courant=None):
212 Dans le cas ou plusieurs validateurs sont reliés par un OU
213 tous les validateurs doivent proposer un choix pour
214 qu'on considère que leur union propose un choix.
215 Tous les choix proposés par les validateurs sont réunis (opérateur d'union)
216 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
217 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
220 for validator in self.validators:
221 v_into=validator.get_into(liste_courante,into_courant)
224 validator_into.extend(v_into)
225 return validator_into
230 return "\n et ".join([v.info() for v in self.validators])
232 def info_erreur_item(self):
235 for v in self.validators:
236 if v.info_erreur_item() != " " :
238 chaine=v.info_erreur_item()
241 chaine=chaine+" \n et "+v.info_erreur_item()
244 def info_erreur_liste(self):
246 for v in self.validators:
247 if v.info_erreur_liste() != " " :
249 chaine=v.info_erreur_liste()
252 chaine=chaine+" \n et "+v.info_erreur_liste()
255 def verif_item(self,valeur):
256 for validator in self.validators:
257 v=validator.verif_item(valeur)
259 # L'info n'est probablement pas la meme que pour verif ???
260 self.local_info=validator.info()
266 Si plusieurs validateurs sont reliés par un ET
267 il faut que tous les validateurs attendent une liste
268 pour qu'on considère que leur intersection attende une liste.
269 Exemple Range(2,5) ET Card(1) n'attend pas une liste
270 Range(2,5) ET Pair attend une liste
272 for validator in self.validators:
273 v=validator.is_list()
280 Dans le cas ou plusieurs validateurs sont reliés par un ET
281 il suffit qu'un seul validateur propose un choix pour
282 qu'on considère que leur intersection propose un choix.
283 Exemple : Enum(1,2,3) ET entier pair, propose un choix
284 En revanche, entier pair ET superieur à 10 ne propose pas de choix
286 for validator in self.validators:
287 v=validator.has_into()
293 def get_into(self,liste_courante=None,into_courant=None):
295 Dans le cas ou plusieurs validateurs sont reliés par un ET
296 il suffit qu'un seul validateur propose un choix pour
297 qu'on considère que leur intersection propose un choix.
299 Tous les choix proposés par les validateurs sont croisés (opérateur d'intersection)
300 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
301 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix
303 for validator in self.validators:
304 into_courant=validator.get_into(liste_courante,into_courant)
305 if into_courant in ([],None):
309 class CardVal(Valid):
311 return "longueur de liste comprise entre %s et %s" % (self.min,self.max)
314 if self.max == '**' or self.max > 1:
319 def verif_item(self,valeur):
322 def valide_liste_partielle(self,liste_courante=None):
325 if liste_courante != None :
326 if len(liste_courante) > self.max :
330 def get_into(self,liste_courante=None,into_courant=None):
331 if into_courant is None:
333 elif liste_courante is None:
335 elif self.max == '**':
337 elif len(liste_courante) < self.max:
342 def info_erreur_liste(self):
343 return "La cardinalité de la liste doit être comprise entre %s et %s" % (self.min,self.max)
345 class ListVal(Valid):
349 def get_into(self,liste_courante=None,into_courant=None):
351 Cette méthode get_into effectue un traitement général qui consiste
352 a filtrer la liste de choix into_courant, si elle existe, en ne conservant
353 que les valeurs valides (appel de la méthode valid)
355 if into_courant is None:
359 for e in into_courant:
361 liste_choix.append(e)
364 class EnumVal(ListVal):
365 def verif_item(self,valeur):
366 if valeur not in self.into:return 0
372 def get_into(self,liste_courante=None,into_courant=None):
373 if into_courant is None:
374 liste_choix= list(self.into)
377 for e in into_courant:
379 liste_choix.append(e)
382 def info_erreur_item(self):
383 return "La valeur n'est pas dans la liste des choix possibles"
385 class LongStr(ListVal):
386 def info_erreur_item(self):
387 return "Longueur de la chaine incorrecte"
389 def verif_item(self,valeur):
392 if valeur[0]=="'" and valeur[-1]=="'" :
395 if len(valeur) < low :return 0
396 if len(valeur) > high:return 0
399 class RangeVal(ListVal):
400 def verif_item(self,valeur):
401 if valeur < self.low :return 0
402 if valeur > self.high:return 0
405 def info_erreur_item(self) :
406 return "La valeur doit être comprise entre %s et %s" % (self.low,self.high)
408 class TypeVal(ListVal):
409 def verif_item(self,valeur):
416 class PairVal(ListVal):
418 def info_erreur_item(self):
419 return "La valeur saisie doit être paire"
421 #ATTENTION METHODE SURCHARGEE: a resorber dans une future version
422 def verif_item(self,valeur):
423 if self.is_eval(valeur):
425 elif self.is_param(valeur):
427 elif self.is_unknown(valeur):
429 return valeur % 2 == 0
431 def verif(self,valeur):
432 if self.is_param(valeur):
434 if type(valeur) in (types.ListType,types.TupleType):
436 if not self.verif_item(val):
440 return self.verif_item(valeur)
442 def verif_old(self,valeur):
443 print "Ihm.I_MCSIMP.PairVal.verif: ",valeur
444 return self.surcharge_verif(Noyau.N_VALIDATOR.PairVal.verif,valeur)
446 class InstanceVal(ListVal):
447 def verif_item(self,valeur):
448 if not isinstance(valeur,self.aClass): return 0
451 class NoRepeat(ListVal):
453 return "pas de presence de doublon dans la liste"
455 def info_erreur_liste(self):
456 return "Les doublons ne sont pas permis"
458 def verif_item(self,valeur):
461 def get_into(self,liste_courante=None,into_courant=None):
463 Methode get_into spécifique pour validateur NoRepeat
464 on retourne une liste de choix qui ne contient aucune valeur de into_courant
465 déjà contenue dans liste_courante
467 if into_courant is None:
471 for e in into_courant:
472 if e in liste_choix: continue
473 if liste_courante is not None and e in liste_courante: continue
474 liste_choix.append(e)
477 class OrdList(ListVal):
478 def verif_item(self,valeur):
481 def get_into(self,liste_courante=None,into_courant=None):
483 Methode get_into spécifique pour validateur OrdList
484 on retourne une liste de choix qui ne contient aucune valeur de into_courant
485 dont la valeur est inférieure à la dernière valeur de liste_courante, si
486 elle est différente de None.
488 if into_courant is None:
490 elif not liste_courante :
494 last_val=liste_choix[-1]
495 for e in into_courant:
496 if self.ord=='croissant' and e <= last_val:continue
497 if self.ord=='decroissant' and e >= last_val:continue
498 liste_choix.append(e)
501 def info_erreur_liste(self) :
502 return "La liste doit être en ordre "+self.ord