1 #@ MODIF N_VALIDATOR Noyau DATE 11/10/2010 AUTEUR COURTOIS M.COURTOIS
2 # -*- coding: iso-8859-1 -*-
3 # RESPONSABLE COURTOIS M.COURTOIS
4 # CONFIGURATION MANAGEMENT OF EDF VERSION
5 # ======================================================================
6 # COPYRIGHT (C) 1991 - 2003 EDF R&D WWW.CODE-ASTER.ORG
7 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
8 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
9 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
10 # (AT YOUR OPTION) ANY LATER VERSION.
12 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
13 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
14 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
15 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
17 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
18 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
19 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
20 # ======================================================================
23 Ce module contient toutes les classes necessaires pour
24 implanter le concept de validateur dans Accas
28 from N_ASSD import ASSD
29 from N_types import is_int, is_float_or_int, is_complex, is_number, is_str, is_enum
32 class ValError(Exception):pass
35 if hasattr(cls,"__mro__"):return cls.__mro__
37 for base in cls.__bases__:
38 mro.extend(cls_mro(base))
42 def __init__(self,name):
47 def register(self, T, A):
51 # (a) verifier si l'objet peut s'adapter au protocole
52 adapt = getattr(obj, '__adapt__', None)
54 # on demande à l'objet obj de réaliser lui-meme l'adaptation
57 # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
59 for T in cls_mro(obj.__class__):
60 if T in self.registry:
61 return self.registry[T](obj,self,**self.args)
63 # (c) utiliser l'adapteur par defaut
64 return self.default(obj,**self.args)
66 def default(self,obj,**args):
67 raise TypeError("Can't adapt %s to %s" %
68 (obj.__class__.__name__, self.name))
70 class PProtocol(Protocol):
71 """Verificateur de protocole paramétré (classe de base)"""
72 #Protocole paramétré. Le registre est unique pour toutes les instances. La methode register est une methode de classe
74 def __init__(self,name,**args):
77 def register(cls, T, A):
79 register=classmethod(register)
81 class ListProtocol(Protocol):
82 """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
83 def default(self,obj):
84 if type(obj) is tuple:
85 if len(obj) > 0 and obj[0] in ('RI','MP'):
86 #il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
90 elif type(obj) is list:
93 # pas de valeur affecte. La cardinalite vaut 0
96 #il s'agit d'une chaine. La cardinalite vaut 1
100 # si l'objet supporte len, on a la cardinalite
107 listProto=ListProtocol("list")
110 class TypeProtocol(PProtocol):
111 """Verificateur de type parmi une liste de types possibles"""
112 #pas de registre par instance. Registre unique pour toutes les instances de TypeProtocol
114 def __init__(self,name,typ=None):
115 PProtocol.__init__(self,name,typ=typ)
118 def default(self,obj,typ):
121 for type_permis in typ:
122 if type_permis == 'R':
123 if is_float_or_int(obj): return obj
124 elif type_permis == 'I':
125 if is_int(obj): return obj
126 elif type_permis == 'C':
127 if self.is_complexe(obj): return obj
128 elif type_permis == 'TXM':
129 if is_str(obj): return obj
130 elif type_permis == 'shell':
131 if is_str(obj): return obj
132 elif type_permis == 'Fichier' :
134 if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj):
136 else : raise ValError("%s n'est pas un fichier valide" % repr(obj))
137 elif type_permis == 'FichierNoAbs' :
139 if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")):
141 else : raise ValError("%s n'est pas un fichier valide" % repr(obj))
142 elif type(type_permis) == types.ClassType or isinstance(type_permis,type):
144 if self.is_object_from(obj,type_permis): return obj
145 except Exception, err:
147 elif type(type_permis) == types.InstanceType or isinstance(type_permis,object):
149 if type_permis.__convert__(obj): return obj
150 except Exception, err:
153 print "Type non encore géré %s" %`type_permis`
154 raise ValError("%s (de type %s) n'est pas d'un type autorisé: %s %s" % (repr(obj),type(obj),typ, help))
156 def is_complexe(self,valeur):
157 """ Retourne 1 si valeur est un complexe, 0 sinon """
158 if is_number(valeur):
159 # Pour permettre l'utilisation de complexes Python (accepte les entiers et réels)
161 elif type(valeur) != tuple :
162 # On n'autorise pas les listes pour les complexes
164 elif len(valeur) != 3:
167 # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
168 # valeur suivie de 2 reels.
169 if valeur[0].strip() in ('RI','MP'):
171 v1=reelProto.adapt(valeur[1]),reelProto.adapt(valeur[2])
178 def is_object_from(self,objet,classe):
180 Retourne 1 si objet est une instance de la classe classe, 0 sinon
182 convert = getattr(classe, '__convert__', None)
183 if convert is not None:
184 # classe verifie les valeurs
188 except ValueError, err:
192 # On accepte les instances de la classe et des classes derivees
193 return isinstance(objet,classe)
195 reelProto=TypeProtocol("reel",typ=('R',))
197 class CardProtocol(PProtocol):
198 """Verificateur de cardinalité """
199 #pas de registre par instance. Registre unique pour toutes les instances
201 def __init__(self,name,min=1,max=1):
202 PProtocol.__init__(self,name,min=min,max=max)
204 def default(self,obj,min,max):
206 if length < min or length >max:
207 raise ValError("Nombre d'arguments de %s incorrect (min = %s, max = %s)" % (repr(obj),min,max) )
210 class IntoProtocol(PProtocol):
211 """Verificateur de choix possibles : liste discrète ou intervalle"""
212 #pas de registre par instance. Registre unique pour toutes les instances
214 def __init__(self,name,into=None,val_min='**',val_max='**'):
215 PProtocol.__init__(self,name,into=into,val_min=val_min,val_max=val_max)
219 def default(self,obj,into,val_min,val_max):
222 raise ValError("La valeur : %s ne fait pas partie des choix possibles %s" % (repr(obj),into) )
224 #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
225 if is_float_or_int(obj):
226 if val_min == '**': val_min = obj -1
227 if val_max == '**': val_max = obj +1
228 if obj < val_min or obj > val_max :
229 raise ValError("La valeur : %s est en dehors du domaine de validité [ %s , %s ]" % (repr(obj),self.val_min,self.val_max) )
233 #exemple de classe pour verificateur de type
234 #on utilise des instances de classe comme type (typ=MinStr(3,6), par exemple)
235 def __init__(self,min,max):
239 def __convert__(self,valeur):
240 if is_str(valeur) and self.min <= len(valeur) <= self.max:return valeur
241 raise ValError("%s n'est pas une chaine de longueur comprise entre %s et %s" % (valeur,self.min,self.max))
244 return "TXM de longueur entre %s et %s" %(self.min,self.max)
246 class Valid(PProtocol):
248 Cette classe est la classe mere des validateurs Accas
249 Elle doit etre derivee
250 Elle presente la signature des methodes indispensables pour son bon
251 fonctionnement et dans certains cas leur comportement par défaut.
253 @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
254 @type cata_info: C{string}
257 def __init__(self,**args):
258 PProtocol.__init__(self,"valid",**args)
262 Cette methode retourne une chaine de caractères informative sur
263 la validation demandée par le validateur. Elle est utilisée
264 pour produire le compte-rendu de validité du mot clé associé.
266 return "valeur valide"
270 Cette methode retourne une chaine de caractère qui permet
271 de construire un message d'aide en ligne.
272 En général, le message retourné est le meme que celui retourné par la
277 def info_erreur_item(self):
279 Cette méthode permet d'avoir un message d'erreur pour un item
280 dans une liste dans le cas ou le validateur fait des vérifications
281 sur les items d'une liste. Si le validateur fait seulement des
282 vérifications sur la liste elle meme et non sur ses items, la méthode
283 doit retourner une chaine vide.
287 def info_erreur_liste(self):
289 Cette méthode a un comportement complémentaire de celui de
290 info_erreur_item. Elle retourne un message d'erreur lié uniquement
291 aux vérifications sur la liste elle meme et pas sur ses items.
292 Dans le cas où le validateur ne fait pas de vérification sur des
293 listes, elle retourne une chaine vide
297 def verif(self,valeur):
299 Cette methode sert a verifier si la valeur passee en argument est consideree
300 comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
301 (valide) sinon 0 (invalide).
303 @type valeur: tout type python
304 @param valeur: valeur du mot cle a valider
306 @return: indicateur de validite 1 (valide) ou 0 (invalide)
308 raise "Must be implemented"
310 def verif_item(self,valeur):
312 La methode verif du validateur effectue une validation complete de
313 la valeur. valeur peut etre un scalaire ou une liste. Le validateur
314 doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
315 methode is_list doit retourner 1).
316 La methode valid_item sert pour effectuer des validations partielles
317 de liste. Elle doit uniquement verifier la validite d'un item de
318 liste mais pas les caracteristiques de la liste.
322 def valide_liste_partielle(self,liste_courante):
324 Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
325 ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
326 veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
328 En général un validateur effectue la meme validation pour les listes partielles et les
331 return self.verif(liste_courante)
333 def verif_cata(self):
335 Cette methode sert a realiser des verifications du validateur lui meme.
336 Elle est facultative et retourne 1 (valide) par defaut.
337 Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
338 parametres de definition ne sont pas corrects.
339 La raison de l'invalidite est stockee dans l'attribut cata_info.
342 @return: indicateur de validite 1 (valide) ou 0 (invalide)
348 Cette méthode retourne un entier qui indique si le validateur
349 permet les listes (valeur 1) ou ne les permet pas (valeur 0).
350 Par défaut, un validateur n'autorise que des scalaires.
356 Cette méthode retourne un entier qui indique si le validateur
357 propose une liste de choix (valeur 1) ou n'en propose pas.
358 Par défaut, un validateur n'en propose pas.
362 def get_into(self,liste_courante=None,into_courant=None):
364 Cette méthode retourne la liste de choix proposée par le validateur.
365 Si le validateur ne propose pas de liste de choix, la méthode
367 L'argument d'entrée liste_courante, s'il est différent de None, donne
368 la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
369 méthode get_into doit calculer la liste des choix en en tenant
370 compte. Par exemple, si le validateur n'autorise pas les répétitions,
371 la liste des choix retournée ne doit pas contenir les choix déjà
372 contenus dans liste_courante.
373 L'argument d'entrée into_courant, s'il est différent de None, donne
374 la liste des choix proposés par d'autres validateurs. Dans ce cas,
375 la méthode get_into doit calculer la liste des choix à retourner
376 en se limitant à cette liste initiale. Par exemple, si into_courant
377 vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
378 la méthode ne doit retourner que (3,).
380 La méthode get_into peut retourner une liste vide [], ce qui veut
381 dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
382 peut etre normale : l''utilisateur a utilisé tous les choix, ou
383 résulter d'une incohérence des validateurs :
384 choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
385 faire la différence entre ces deux situations.
389 class ListVal(Valid):
391 Cette classe sert de classe mère pour tous les validateurs qui acceptent
397 def get_into(self,liste_courante=None,into_courant=None):
399 Cette méthode get_into effectue un traitement général qui consiste
400 a filtrer la liste de choix into_courant, si elle existe, en ne
401 conservant que les valeurs valides (appel de la méthode valid).
403 if into_courant is None:
407 for e in into_courant:
409 liste_choix.append(e)
412 def convert(self,valeur):
414 Méthode convert pour les validateurs de listes. Cette méthode
415 fait appel à la méthode convert_item sur chaque élément de la
420 self.convert_item(val)
423 return self.convert_item(valeur)
425 def verif(self,valeur):
427 Méthode verif pour les validateurs de listes. Cette méthode
428 fait appel à la méthode verif_item sur chaque élément de la
429 liste. Si valeur est un paramètre, on utilise sa valeur effective
434 if not self.verif_item(val):
438 return self.verif_item(valeur)
440 class Compulsory(ListVal):
442 Validateur operationnel
443 Verification de la présence obligatoire d'un élément dans une liste
446 def __init__(self,elem=()):
447 if not is_enum(elem): elem=(elem,)
448 Valid.__init__(self,elem=elem)
453 return "valeur %s obligatoire" % `self.elem`
455 def default(self,valeur,elem):
458 def verif_item(self,valeur):
461 def convert(self,valeur):
465 if v in elem:elem.remove(v)
467 raise ValError("%s ne contient pas les elements obligatoires : %s " %(valeur,elem))
473 def verif(self,valeur):
474 if not is_enum(valeur):
478 for val in self.elem :
479 if val not in liste : return 0
482 def info_erreur_item(self):
483 return "La valeur n'est pas dans la liste des choix possibles"
485 class NoRepeat(ListVal):
487 Validateur operationnel
488 Verification d'absence de doublons dans la liste.
495 return ": pas de présence de doublon dans la liste"
497 def info_erreur_liste(self):
498 return "Les doublons ne sont pas permis"
500 def default(self,valeur):
501 if valeur in self.liste : raise ValError("%s est un doublon" % valeur)
504 def convert(self,valeur):
511 def verif_item(self,valeur):
514 def verif(self,valeur):
518 if liste.count(val)!=1 : return 0
523 def get_into(self,liste_courante=None,into_courant=None):
525 Methode get_into spécifique pour validateur NoRepeat, on retourne
526 une liste de choix qui ne contient aucune valeur de into_courant
527 déjà contenue dans liste_courante
529 if into_courant is None:
533 for e in into_courant:
534 if e in liste_choix: continue
535 if liste_courante is not None and e in liste_courante: continue
536 liste_choix.append(e)
539 class LongStr(ListVal):
541 Validateur operationnel
542 Verification de la longueur d une chaine
544 def __init__(self,low,high):
545 ListVal.__init__(self,low=low,high=high)
551 return "longueur de la chaine entre %s et %s" %(self.low,self.high)
553 def info_erreur_item(self):
554 return "Longueur de la chaine incorrecte"
556 def convert(self,valeur):
561 def verif_item(self,valeur):
568 def default(self,valeur,low,high):
569 if not is_str(valeur):
570 raise ValError("%s n'est pas une string" % repr(valeur))
571 if valeur[0]=="'" and valeur[-1]=="'" :
574 if len(valeur) < low or len(valeur) > high :
575 raise ValError("%s n'est pas de la bonne longueur" % repr(valeur))
578 class OnlyStr(ListVal):
580 Validateur operationnel
581 Valide que c'est une chaine
584 ListVal.__init__(self)
588 return "regarde si c'est une chaine"
590 def info_erreur_item(self):
591 return "Ce n'est pas une chain"
593 def convert(self,valeur):
598 def verif_item(self,valeur):
605 def default(self,valeur):
606 if not is_str(valeur):
607 raise ValError("%s n'est pas une string" % repr(valeur))
610 class OrdList(ListVal):
612 Validateur operationnel
613 Verification qu'une liste est croissante ou decroissante
615 def __init__(self,ord):
616 ListVal.__init__(self,ord=ord)
621 return "liste %s" % self.ord
623 def info_erreur_liste(self) :
624 return "La liste doit etre en ordre "+self.ord
626 def convert(self,valeur):
633 def default(self,valeur,ord):
634 if self.ord=='croissant':
635 if self.val is not None and valeur<self.val:
636 raise ValError("%s n'est pas par valeurs croissantes" % repr(self.liste))
637 elif self.ord=='decroissant':
638 if self.val is not None and valeur > self.val:
639 raise ValError("%s n'est pas par valeurs decroissantes" % repr(self.liste))
643 def verif_item(self,valeur):
646 def get_into(self,liste_courante=None,into_courant=None):
648 Methode get_into spécifique pour validateur OrdList, on retourne
649 une liste de choix qui ne contient aucune valeur de into_courant
650 dont la valeur est inférieure à la dernière valeur de
651 liste_courante, si elle est différente de None.
653 if into_courant is None:
655 elif not liste_courante :
659 last_val=liste_choix[-1]
660 for e in into_courant:
661 if self.ord=='croissant' and e <= last_val:continue
662 if self.ord=='decroissant' and e >= last_val:continue
663 liste_choix.append(e)
668 Validateur operationnel
669 Cette classe est un validateur qui controle une liste de validateurs
670 Elle verifie qu'au moins un des validateurs de la liste valide la valeur
672 def __init__(self,validators=()):
673 if not is_enum(validators):
674 validators=(validators,)
676 for validator in validators:
677 if type(validator) == types.FunctionType:
678 self.validators.append(FunctionVal(validator))
680 self.validators.append(validator)
684 return "\n ou ".join([v.info() for v in self.validators])
686 def convert(self,valeur):
687 for validator in self.validators:
689 return validator.convert(valeur)
692 raise ValError("%s n'est pas du bon type" % repr(valeur))
694 def info_erreur_item(self):
696 for v in self.validators:
697 err=v.info_erreur_item()
698 if err != " " : l.append(err)
699 chaine=" \n ou ".join(l)
702 def info_erreur_liste(self):
704 for v in self.validators:
705 err=v.info_erreur_liste()
706 if err != " " : l.append(err)
707 chaine=" \n ou ".join(l)
712 Si plusieurs validateurs sont reliés par un OU
713 il suffit qu'un seul des validateurs attende une liste
714 pour qu'on considère que leur union attend une liste.
716 for validator in self.validators:
717 v=validator.is_list()
722 def verif(self,valeur):
723 for validator in self.validators:
724 v=validator.verif(valeur)
729 def verif_item(self,valeur):
730 for validator in self.validators:
731 v=validator.verif_item(valeur)
736 def verif_cata(self):
738 for validator in self.validators:
739 v=validator.verif_cata()
740 if not v :infos.append(validator.cata_info)
742 self.cata_info="\n".join(infos)
749 Dans le cas ou plusieurs validateurs sont reliés par un OU
750 il faut que tous les validateurs proposent un choix pour
751 qu'on considère que leur union propose un choix.
752 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
753 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
755 for validator in self.validators:
756 v=validator.has_into()
761 def get_into(self,liste_courante=None,into_courant=None):
763 Dans le cas ou plusieurs validateurs sont reliés par un OU
764 tous les validateurs doivent proposer un choix pour
765 qu'on considère que leur union propose un choix. Tous les choix
766 proposés par les validateurs sont réunis (opérateur d'union).
767 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
768 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
772 for validator in self.validators:
773 v_into=validator.get_into(liste_courante,into_courant)
776 validator_into.extend(v_into)
777 return validator_into
779 def valide_liste_partielle(self,liste_courante=None):
781 Méthode de validation de liste partielle pour le validateur Or.
782 Si un des validateurs gérés par le validateur Or considère la
783 liste comme valide, le validateur Or la considère comme valide.
785 for validator in self.validators:
786 v=validator.valide_liste_partielle(liste_courante)
793 Validateur operationnel
794 Cette classe est un validateur qui controle une liste de validateurs
795 Elle verifie que tous les validateurs de la liste valident la valeur
797 def __init__(self,validators=()):
798 if not is_enum(validators):
799 validators=(validators,)
801 for validator in validators:
802 if type(validator) == types.FunctionType:
803 self.validators.append(FunctionVal(validator))
805 self.validators.append(validator)
806 if hasattr(validator,'fonctions'):
807 for fonction in validator.fonctions :
808 f=getattr(validator,fonction)
809 setattr(self,fonction,f)
813 return "\n et ".join([v.info() for v in self.validators])
815 def convert(self,valeur):
816 for validator in self.validators:
817 valeur=validator.convert(valeur)
820 def info_erreur_item(self):
823 for v in self.validators:
824 if v.info_erreur_item() != " " :
826 chaine=v.info_erreur_item()
829 chaine=chaine+" \n et "+v.info_erreur_item()
832 def info_erreur_liste(self):
834 for v in self.validators:
835 if v.info_erreur_liste() != " " :
837 chaine=v.info_erreur_liste()
840 chaine=chaine+" \n et "+v.info_erreur_liste()
843 def verif(self,valeur):
844 for validator in self.validators:
845 v=validator.verif(valeur)
847 self.local_info=validator.info()
851 def verif_item(self,valeur):
852 for validator in self.validators:
853 v=validator.verif_item(valeur)
855 # L'info n'est probablement pas la meme que pour verif ???
856 self.local_info=validator.info()
860 def verif_cata(self):
862 for validator in self.validators:
863 v=validator.verif_cata()
864 if not v :infos.append(validator.cata_info)
866 self.cata_info="\n".join(infos)
871 def valide_liste_partielle(self,liste_courante=None):
873 Méthode de validation de liste partielle pour le validateur And.
874 Tous les validateurs gérés par le validateur And doivent considérer
875 la liste comme valide, pour que le validateur And la considère
878 for validator in self.validators:
879 v=validator.valide_liste_partielle(liste_courante)
886 Si plusieurs validateurs sont reliés par un ET
887 il faut que tous les validateurs attendent une liste
888 pour qu'on considère que leur intersection attende une liste.
889 Exemple Range(2,5) ET Card(1) n'attend pas une liste
890 Range(2,5) ET Pair attend une liste
892 for validator in self.validators:
893 v=validator.is_list()
900 Dans le cas ou plusieurs validateurs sont reliés par un ET
901 il suffit qu'un seul validateur propose un choix pour
902 qu'on considère que leur intersection propose un choix.
903 Exemple : Enum(1,2,3) ET entier pair, propose un choix
904 En revanche, entier pair ET superieur à 10 ne propose pas de choix
906 for validator in self.validators:
907 v=validator.has_into()
912 def get_into(self,liste_courante=None,into_courant=None):
914 Dans le cas ou plusieurs validateurs sont reliés par un ET
915 il suffit qu'un seul validateur propose un choix pour
916 qu'on considère que leur intersection propose un choix. Tous les
917 choix proposés par les validateurs sont croisés (opérateur
919 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
920 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
922 for validator in self.validators:
923 into_courant=validator.get_into(liste_courante,into_courant)
924 if into_courant in ([],None):break
927 def do_liste(validators):
929 Convertit une arborescence de validateurs en OrVal ou AndVal
930 validators est une liste de validateurs ou de listes ou de tuples
933 for validator in validators:
934 if type(validator) == types.FunctionType:
935 valids.append(FunctionVal(validator))
936 elif type(validator) is tuple:
937 valids.append(OrVal(do_liste(validator)))
938 elif type(validator) is list:
939 valids.append(AndVal(do_liste(validator)))
941 valids.append(validator)
944 def validatorFactory(validator):
945 if type(validator) == types.FunctionType:
946 return FunctionVal(validator)
947 elif type(validator) is tuple:
948 return OrVal(do_liste(validator))
949 elif type(validator) is list:
950 return AndVal(do_liste(validator))
954 # Ci-dessous : exemples de validateur (peu testés)
956 class RangeVal(ListVal):
958 Exemple de classe validateur : verification qu'une valeur
959 est dans un intervalle.
960 Pour une liste on verifie que tous les elements sont
962 Susceptible de remplacer les attributs "vale_min" "vale_max"
965 def __init__(self,low,high):
968 self.cata_info="%s doit etre inferieur a %s" %(low,high)
971 return "valeur dans l'intervalle %s , %s" %(self.low,self.high)
973 def convert_item(self,valeur):
974 if valeur > self.low and valeur < self.high:return valeur
975 raise ValError("%s devrait etre comprise entre %s et %s" %(valeur,self.low,self.high))
977 def verif_item(self,valeur):
978 return valeur > self.low and valeur < self.high
980 def info_erreur_item(self) :
981 return "La valeur doit etre comprise entre %s et %s" % (self.low,
984 def verif_cata(self):
985 if self.low > self.high : return 0
988 class CardVal(Valid):
990 Exemple de classe validateur : verification qu'une liste est
991 d'une longueur superieur a un minimum (min) et inferieure
993 Susceptible de remplacer les attributs "min" "max" dans les
996 def __init__(self,min='**',max='**'):
999 self.cata_info="%s doit etre inferieur a %s" % (min,max)
1002 return "longueur de liste comprise entre %s et %s" % (self.min,self.max)
1004 def info_erreur_liste(self):
1005 return "Le cardinal de la liste doit etre compris entre %s et %s" % (self.min,self.max)
1008 return self.max == '**' or self.max > 1
1010 def get_into(self,liste_courante=None,into_courant=None):
1011 if into_courant is None:
1013 elif liste_courante is None:
1015 elif self.max == '**':
1017 elif len(liste_courante) < self.max:
1022 def convert(self,valeur):
1025 elif valeur is None:
1029 if self.max != '**' and l > self.max:raise ValError("%s devrait etre de longueur inferieure a %s" %(valeur,self.max))
1030 if self.min != '**' and l < self.min:raise ValError("%s devrait etre de longueur superieure a %s" %(valeur,self.min))
1033 def verif_item(self,valeur):
1036 def verif(self,valeur):
1038 if self.max != '**' and len(valeur) > self.max:return 0
1039 if self.min != '**' and len(valeur) < self.min:return 0
1042 if self.max != '**' and 1 > self.max:return 0
1043 if self.min != '**' and 1 < self.min:return 0
1046 def verif_cata(self):
1047 if self.min != '**' and self.max != '**' and self.min > self.max : return 0
1050 def valide_liste_partielle(self,liste_courante=None):
1052 if liste_courante != None :
1053 if len(liste_courante) > self.max :
1057 class PairVal(ListVal):
1059 Exemple de classe validateur : verification qu'une valeur
1061 Pour une liste on verifie que tous les elements sont
1065 ListVal.__init__(self)
1069 return "valeur paire"
1071 def info_erreur_item(self):
1072 return "La valeur saisie doit etre paire"
1074 def convert(self,valeur):
1077 if v % 2 != 0:raise ValError("%s contient des valeurs non paires" % repr(valeur))
1080 def default(self,valeur):
1083 def verif_item(self,valeur):
1084 if type(valeur) not in (int,long):
1086 return valeur % 2 == 0
1088 def verif(self,valeur):
1091 if val % 2 != 0:return 0
1094 if valeur % 2 != 0:return 0
1097 class EnumVal(ListVal):
1099 Exemple de classe validateur : verification qu'une valeur
1100 est prise dans une liste de valeurs.
1101 Susceptible de remplacer l attribut "into" dans les catalogues
1103 def __init__(self,into=()):
1104 if not is_enum(into):
1110 return "valeur dans %s" % `self.into`
1112 def convert_item(self,valeur):
1113 if valeur in self.into:return valeur
1114 raise ValError("%s contient des valeurs hors des choix possibles: %s " %(valeur,self.into))
1116 def verif_item(self,valeur):
1117 if valeur not in self.into:return 0
1123 def get_into(self,liste_courante=None,into_courant=None):
1124 if into_courant is None:
1125 liste_choix= list(self.into)
1128 for e in into_courant:
1130 liste_choix.append(e)
1133 def info_erreur_item(self):
1134 return "La valeur n'est pas dans la liste des choix possibles"
1136 def ImpairVal(valeur):
1138 Exemple de validateur
1139 Cette fonction est un validateur. Elle verifie que la valeur passee
1140 est bien un nombre impair.
1144 if val % 2 != 1:return 0
1147 if valeur % 2 != 1:return 0
1150 ImpairVal.info="valeur impaire"
1154 Exemple de validateur
1155 Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1156 que la somme des cles A et B vaut une valeur donnee
1157 en parametre du validateur
1159 def __init__(self,somme=10):
1164 return "valeur %s pour la somme des cles A et B " % self.somme
1166 def verif(self,valeur):
1169 if not val.has_key("A"):return 0
1170 if not val.has_key("B"):return 0
1171 if val["A"]+val["B"] != self.somme:return 0
1174 if not valeur.has_key("A"):return 0
1175 if not valeur.has_key("B"):return 0
1176 if valeur["A"]+valeur["B"] != self.somme:return 0
1179 class FunctionVal(Valid):
1181 Exemple de validateur
1182 Cette classe est un validateur qui est initialise avec une fonction
1184 def __init__(self,function):
1185 self.function=function
1188 return self.function.info
1190 def verif(self,valeur):
1191 return self.function(valeur)
1193 #MC ca ne devrait plus servir !
1194 CoercableFuncs = { types.IntType: int,
1195 types.LongType: long,
1196 types.FloatType: float,
1197 types.ComplexType: complex,
1198 types.UnicodeType: unicode }
1200 class TypeVal(ListVal):
1202 Exemple de validateur
1203 Cette classe est un validateur qui controle qu'une valeur
1204 est bien du type Python attendu.
1205 Pour une liste on verifie que tous les elements sont du bon type.
1206 Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1207 alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1209 def __init__(self, aType):
1210 #Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1211 #type(1) == int;type(0.2)==float;etc.
1212 if type(aType) != types.TypeType:
1216 self.coerce=CoercableFuncs[ aType ]
1218 self.coerce = self.identity
1221 return "valeur de %s" % self.aType
1223 def identity ( self, value ):
1224 if type( value ) == self.aType:
1228 def convert_item(self,valeur):
1229 return self.coerce(valeur)
1231 def verif_item(self,valeur):
1238 class InstanceVal(ListVal):
1240 Exemple de validateur
1241 Cette classe est un validateur qui controle qu'une valeur est
1242 bien une instance (au sens Python) d'une classe
1243 Pour une liste on verifie chaque element de la liste
1245 def __init__(self,aClass):
1246 #Si aClass est une classe on la memorise dans self.aClass
1247 #sinon c'est une instance dont on memorise la classe
1248 if type(aClass) == types.InstanceType:
1249 #instance ancienne mode
1250 aClass=aClass.__class__
1251 elif type(aClass) == types.ClassType:
1252 #classe ancienne mode
1254 elif type(aClass) == type:
1255 #classe nouvelle mode
1257 elif isinstance(aClass,object):
1258 #instance nouvelle mode
1261 raise ValError("type non supporte")
1266 return "valeur d'instance de %s" % self.aClass.__name__
1268 def verif_item(self,valeur):
1269 if not isinstance(valeur,self.aClass): return 0
1272 class VerifTypeTuple(Valid,ListVal) :
1273 def __init__(self,typeDesTuples):
1274 self.typeDesTuples=typeDesTuples
1275 Valid.__init__(self)
1279 return ": verifie les types dans un tuple"
1281 def info_erreur_liste(self):
1282 return "Les types entres ne sont pas permis"
1284 def default(self,valeur):
1285 #if valeur in self.liste : raise ValError("%s est un doublon" % valeur)
1291 def convert_item(self,valeur):
1292 if len(valeur) != len(self.typeDesTuples):
1293 raise ValError("%s devrait etre de type %s " %(valeur,self.typeDesTuples))
1294 for i in range(len(valeur)) :
1295 ok=self.verifType(valeur[i],self.typeDesTuples[i])
1297 raise ValError("%s devrait etre de type %s " %(valeur,self.typeDesTuples))
1300 def verif_item(self,valeur):
1302 if len(valeur) != len(self.typeDesTuples):
1304 for i in range(len(valeur)) :
1305 ok=self.verifType(valeur[i],self.typeDesTuples[i])
1312 def verifType(self,valeur,type_permis):
1313 if type_permis == 'R':
1314 if type(valeur) in (types.IntType,types.FloatType,types.LongType):return 1
1315 elif type_permis == 'I':
1316 if type(valeur) in (types.IntType,types.LongType):return 1
1317 elif type_permis == 'C':
1318 if self.is_complexe(valeur):return 1
1319 elif type_permis == 'TXM':
1320 if type(valeur)==types.StringType:return 1
1323 def verif(self,valeur):
1324 if type(valeur) in (types.ListType,types.TupleType):
1327 if self.verif_item(val)!=1 : return 0
1330 class VerifExiste(ListVal) :
1332 fonctionne avec into
1333 Met une liste à jour selon les mot clefs existant
1334 exemple si into = ("A","B","C")
1335 si au niveau N du JDC les objets "A" et "C" existe
1336 alors la liste des into deviendra ( "A","C")
1338 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1339 niveauVerif est defini par rapport au Noeud :
1340 exemple niveauVerif = 1 : on verifie les freres
1341 niveauVerif = 2 : on verifie les oncles..
1343 def __init__(self,niveauVerif):
1344 ListVal.__init__(self)
1345 self.niveauVerif=niveauVerif
1347 self.listeDesFreres=()
1348 self.fonctions=('verifie_liste','set_MCSimp')
1353 def verifie_liste(self,liste):
1354 self.set_MCSimp(self.MCSimp)
1356 if not( item in self.listeDesFreres) : return 0
1359 def verif_item(self,valeur):
1360 self.set_MCSimp(self.MCSimp)
1361 if valeur in self.listeDesFreres : return 1
1364 def set_MCSimp(self, MCSimp) :
1372 #on met la liste à jour
1373 parent.forceRecalcul=self.niveauVerif
1374 self.listeDesFreres=parent.liste_mc_presents()
1376 def convert_item(self,valeur):
1377 if valeur in self.listeDesFreres : return valeur
1378 raise ValError(str(valeur)+" n est pas dans " + str(self.listeDesFreres))