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):
68 Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
69 ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
70 veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
72 En général un validateur effectue la meme validation pour les listes partielles et les
75 return self.verif(liste_courante)
77 def verif_item(self,valeur):
79 La methode verif du validateur effectue une validation complete de la valeur.
80 valeur peut etre un scalaire ou une liste. Le validateur doit traiter les 2
81 aspects s'il accepte des listes (dans ce cas la methode is_list doit retourner 1).
82 La methode valid_item sert pour effectuer des validations partielles de liste
83 Elle doit uniquement verifier la validite d'un item de liste mais pas les caracteristiques
88 def get_into(self,liste_courante=None,into_courant=None):
90 Cette méthode retourne la liste de choix proposée par le validateur. Si le validateur ne propose
91 pas de liste de choix, la méthode retourne None.
92 L'argument d'entrée liste_courante, s'il est différent de None, donne la liste des choix déjà
93 effectués par l'utilisateur. Dans ce cas, la méthode get_into doit calculer la liste des choix
94 en en tenant compte. Par exemple, si le validateur n'autorise pas les répétitions, la liste des
95 choix retournée ne doit pas contenir les choix déjà contenus dans liste_courante.
96 L'argument d'entrée into_courant, s'il est différent de None, donne la liste des choix proposés
97 par d'autres validateurs. Dans ce cas, la méthode get_into doit calculer la liste des choix à retourner
98 en se limitant à cette liste initiale. Par exemple, si into_courant vaut (1,2,3) et que le validateur
99 propose la liste de choix (3,4,5), la méthode ne doit retourner que (3,).
101 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
102 Cette situation peut etre normale : l''utilisateur a utilisé tous les choix, ou résulter d'une incohérence
103 des validateurs : choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de faire la différence entre
108 def is_eval(self,valeur):
110 Cette méthode indique si valeur est un objet de type EVAL ou autre
111 que l'on ne cherchera pas à evaluer et qui doit etre considere comme toujours valide
112 Si c'est un objet de ce type elle retourne la valeur 1 sinon la valeur 0
114 if type(valeur) == types.InstanceType :
115 if hasattr(valeur,'__class__'):
116 if valeur.__class__.__name__ in ('EVAL','entier','reel','chaine','complexe','liste','PARAMETRE_EVAL') :
120 def is_param(self,valeur):
122 Cette méthode indique si valeur est un objet de type PARAMETRE
123 dont on cherchera à evaluer la valeur (valeur.valeur)
125 if type(valeur) == types.InstanceType :
126 if valeur.__class__.__name__ in ('PARAMETRE',):
130 def is_unknown(self,valeur):
132 Cette méthode indique si valeur est un objet de type inconnu
133 c'est à dire ni de type EVAL ni de type PARAMETRE
135 if type(valeur) == types.InstanceType :
136 if not self.is_eval(valeur) and not self.is_param(valeur):
140 def surcharge_verif(self,methode_verif_initiale,valeur):
141 if type(valeur) == types.InstanceType :
142 #CCAR: pour le moment on fait comme dans is_entier de V_MCSIMP.py
143 # mais il serait préférable d'appeler une méthode de valeur : valeur.AsType()
144 # qui donnerait le type générique de l'objet.
145 # Pour un objet de "type" entier on obtiendrait par exemple 'I'
146 if valeur.__class__.__name__ in ('EVAL','entier','reel','chaine','complexe','liste','PARAMETRE_EVAL') :
147 # On ne vérifie pas le type d'un EVAL ou d'un objet de classe entier, .... C'est toujours valide
149 elif valeur.__class__.__name__ in ('PARAMETRE',):
150 # Dans le cas d'un parametre, il faut tester si la valeur du parametre est un entier
153 # Objet inconnu : invalide
154 print "Objet non reconnu dans surcharge_verif : %s" %`valeur`
157 return methode_verif_initiale(self,valeur)
159 class FunctionVal(Valid):pass
162 def verif_item(self,valeur):
163 for validator in self.validators:
164 v=validator.verif_item(valeur)
169 def info_erreur_item(self):
171 for v in self.validators:
172 err=v.info_erreur_item()
173 if err != " " : l.append(err)
174 chaine=" \n ou ".join(l)
177 def info_erreur_liste(self):
179 for v in self.validators:
180 err=v.info_erreur_liste()
181 if err != " " : l.append(err)
182 chaine=" \n ou ".join(l)
187 Si plusieurs validateurs sont reliés par un OU
188 il suffit qu'un seul des validateurs attende une liste
189 pour qu'on considère que leur union attende une liste.
191 for validator in self.validators:
192 v=validator.is_list()
199 Dans le cas ou plusieurs validateurs sont reliés par un OU
200 il faut que tous les validateurs proposent un choix pour
201 qu'on considère que leur union propose un choix.
202 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
203 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
205 for validator in self.validators:
206 v=validator.has_into()
211 def get_into(self,liste_courante=None,into_courant=None):
213 Dans le cas ou plusieurs validateurs sont reliés par un OU
214 tous les validateurs doivent proposer un choix pour
215 qu'on considère que leur union propose un choix.
216 Tous les choix proposés par les validateurs sont réunis (opérateur d'union)
217 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
218 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
221 for validator in self.validators:
222 v_into=validator.get_into(liste_courante,into_courant)
225 validator_into.extend(v_into)
226 return validator_into
228 def valide_liste_partielle(self,liste_courante=None):
230 Méthode de validation de liste partielle pour le validateur Or.
231 Si un des validateurs gérés par le validateur Or considère la liste comme
232 valide, le validateur Or la considère comme valide.
234 for validator in self.validators:
235 v=validator.valide_liste_partielle(liste_courante)
242 return "\n et ".join([v.info() for v in self.validators])
244 def info_erreur_item(self):
247 for v in self.validators:
248 if v.info_erreur_item() != " " :
250 chaine=v.info_erreur_item()
253 chaine=chaine+" \n et "+v.info_erreur_item()
256 def info_erreur_liste(self):
258 for v in self.validators:
259 if v.info_erreur_liste() != " " :
261 chaine=v.info_erreur_liste()
264 chaine=chaine+" \n et "+v.info_erreur_liste()
267 def verif_item(self,valeur):
268 for validator in self.validators:
269 v=validator.verif_item(valeur)
271 # L'info n'est probablement pas la meme que pour verif ???
272 self.local_info=validator.info()
276 def valide_liste_partielle(self,liste_courante=None):
278 Méthode de validation de liste partielle pour le validateur And.
279 Tous les validateurs gérés par le validateur And doivent considèrer la liste comme
280 valide, pour que le validateur And la considère comme valide.
282 for validator in self.validators:
283 v=validator.valide_liste_partielle(liste_courante)
290 Si plusieurs validateurs sont reliés par un ET
291 il faut que tous les validateurs attendent une liste
292 pour qu'on considère que leur intersection attende une liste.
293 Exemple Range(2,5) ET Card(1) n'attend pas une liste
294 Range(2,5) ET Pair attend une liste
296 for validator in self.validators:
297 v=validator.is_list()
304 Dans le cas ou plusieurs validateurs sont reliés par un ET
305 il suffit qu'un seul validateur propose un choix pour
306 qu'on considère que leur intersection propose un choix.
307 Exemple : Enum(1,2,3) ET entier pair, propose un choix
308 En revanche, entier pair ET superieur à 10 ne propose pas de choix
310 for validator in self.validators:
311 v=validator.has_into()
317 def get_into(self,liste_courante=None,into_courant=None):
319 Dans le cas ou plusieurs validateurs sont reliés par un ET
320 il suffit qu'un seul validateur propose un choix pour
321 qu'on considère que leur intersection propose un choix.
323 Tous les choix proposés par les validateurs sont croisés (opérateur d'intersection)
324 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
325 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix
327 for validator in self.validators:
328 into_courant=validator.get_into(liste_courante,into_courant)
329 if into_courant in ([],None):
333 class CardVal(Valid):
335 return "longueur de liste comprise entre %s et %s" % (self.min,self.max)
338 if self.max == '**' or self.max > 1:
343 def verif_item(self,valeur):
346 def valide_liste_partielle(self,liste_courante=None):
348 if liste_courante != None :
349 if len(liste_courante) > self.max :
353 def get_into(self,liste_courante=None,into_courant=None):
354 if into_courant is None:
356 elif liste_courante is None:
358 elif self.max == '**':
360 elif len(liste_courante) < self.max:
365 def info_erreur_liste(self):
366 return "La cardinalité de la liste doit être comprise entre %s et %s" % (self.min,self.max)
368 class ListVal(Valid):
372 def get_into(self,liste_courante=None,into_courant=None):
374 Cette méthode get_into effectue un traitement général qui consiste
375 a filtrer la liste de choix into_courant, si elle existe, en ne conservant
376 que les valeurs valides (appel de la méthode valid)
378 if into_courant is None:
382 for e in into_courant:
384 liste_choix.append(e)
387 class EnumVal(ListVal):
388 def verif_item(self,valeur):
389 if valeur not in self.into:return 0
395 def get_into(self,liste_courante=None,into_courant=None):
396 if into_courant is None:
397 liste_choix= list(self.into)
400 for e in into_courant:
402 liste_choix.append(e)
405 def info_erreur_item(self):
406 return "La valeur n'est pas dans la liste des choix possibles"
408 class LongStr(ListVal):
409 def info_erreur_item(self):
410 return "Longueur de la chaine incorrecte"
412 def verif_item(self,valeur):
415 if valeur[0]=="'" and valeur[-1]=="'" :
418 if len(valeur) < low :return 0
419 if len(valeur) > high:return 0
422 class RangeVal(ListVal):
423 def verif_item(self,valeur):
424 if valeur < self.low :return 0
425 if valeur > self.high:return 0
428 def info_erreur_item(self) :
429 return "La valeur doit être comprise entre %s et %s" % (self.low,self.high)
431 CoercableFuncs = { types.IntType: int,
432 types.LongType: long,
433 types.FloatType: float,
434 types.ComplexType: complex,
435 types.UnicodeType: unicode }
437 class TypeVal(ListVal):
439 Cette classe est un validateur qui controle qu'une valeur
440 est bien du type Python attendu.
441 Pour une liste on verifie que tous les elements sont du bon type.
443 def __init__(self, aType):
444 if type(aType) != types.TypeType:
448 self.coerce=CoercableFuncs[ aType ]
450 self.coerce = self.identity
453 return "valeur de %s" % self.aType
455 def identity ( self, value ):
456 if type( value ) == self.aType:
460 def verif(self,valeur):
461 if type(valeur) in (types.ListType,types.TupleType):
463 valid=self.verif_item(val)
464 if valid == 0:return 0
467 return self.verif_item(valeur)
469 def verif_item(self,valeur):
476 class PairVal(ListVal):
478 def info_erreur_item(self):
479 return "La valeur saisie doit être paire"
481 #ATTENTION METHODE SURCHARGEE: a resorber dans une future version
482 def verif_item(self,valeur):
483 if self.is_eval(valeur):
485 elif self.is_param(valeur):
487 elif self.is_unknown(valeur):
489 return valeur % 2 == 0
491 def verif(self,valeur):
492 if self.is_param(valeur):
494 if type(valeur) in (types.ListType,types.TupleType):
496 if not self.verif_item(val):
500 return self.verif_item(valeur)
502 def verif_old(self,valeur):
503 print "Ihm.I_MCSIMP.PairVal.verif: ",valeur
504 return self.surcharge_verif(Noyau.N_VALIDATOR.PairVal.verif,valeur)
506 class InstanceVal(ListVal):
507 def verif_item(self,valeur):
508 if not isinstance(valeur,self.aClass): return 0
511 class NoRepeat(ListVal):
513 return "pas de presence de doublon dans la liste"
515 def info_erreur_liste(self):
516 return "Les doublons ne sont pas permis"
518 def verif_item(self,valeur):
521 def get_into(self,liste_courante=None,into_courant=None):
523 Methode get_into spécifique pour validateur NoRepeat
524 on retourne une liste de choix qui ne contient aucune valeur de into_courant
525 déjà contenue dans liste_courante
527 if into_courant is None:
531 for e in into_courant:
532 if e in liste_choix: continue
533 if liste_courante is not None and e in liste_courante: continue
534 liste_choix.append(e)
537 class OrdList(ListVal):
538 def verif_item(self,valeur):
541 def get_into(self,liste_courante=None,into_courant=None):
543 Methode get_into spécifique pour validateur OrdList
544 on retourne une liste de choix qui ne contient aucune valeur de into_courant
545 dont la valeur est inférieure à la dernière valeur de liste_courante, si
546 elle est différente de None.
548 if into_courant is None:
550 elif not liste_courante :
554 last_val=liste_choix[-1]
555 for e in into_courant:
556 if self.ord=='croissant' and e <= last_val:continue
557 if self.ord=='decroissant' and e >= last_val:continue
558 liste_choix.append(e)
561 def info_erreur_liste(self) :
562 return "La liste doit être en ordre "+self.ord