2 # person_in_charge: mathieu.courtois at edf.fr
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2015 EDF R&D WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
18 # ======================================================================
21 Ce module contient toutes les classes necessaires pour
22 implanter le concept de validateur dans Accas
27 from N_ASSD import ASSD
28 from N_types import is_int, is_float_or_int, is_complex, is_number, is_str, is_sequence
29 from strfunc import convert, ufmt
32 class ValError(Exception):
37 if hasattr(cls, "__mro__"):
40 for base in cls.__bases__:
41 mro.extend(cls_mro(base))
47 def __init__(self, name):
52 def register(self, T, A):
56 # (a) verifier si l'objet peut s'adapter au protocole
57 adapt = getattr(obj, '__adapt__', None)
59 # on demande à l'objet obj de réaliser lui-meme l'adaptation
62 # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
64 for T in cls_mro(obj.__class__):
65 if T in self.registry:
66 return self.registry[T](obj, self, **self.args)
68 # (c) utiliser l'adapteur par defaut
69 return self.default(obj, **self.args)
71 def default(self, obj, **args):
72 raise TypeError("Can't adapt %s to %s" %
73 (obj.__class__.__name__, self.name))
76 class PProtocol(Protocol):
78 """Verificateur de protocole paramétré (classe de base)"""
79 # Protocole paramétré. Le registre est unique pour toutes les instances.
80 # La methode register est une methode de classe
83 def __init__(self, name, **args):
87 def register(cls, T, A):
89 register = classmethod(register)
92 class ListProtocol(Protocol):
94 """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
96 def default(self, obj):
97 if type(obj) is tuple:
98 if len(obj) > 0 and obj[0] in ('RI', 'MP'):
99 # il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
103 elif type(obj) is list:
106 # pas de valeur affecte. La cardinalite vaut 0
109 # il s'agit d'une chaine. La cardinalite vaut 1
113 # si l'objet supporte len, on a la cardinalite
120 listProto = ListProtocol("list")
123 class TypeProtocol(PProtocol):
125 """Verificateur de type parmi une liste de types possibles"""
126 # pas de registre par instance. Registre unique pour toutes les instances
130 def __init__(self, name, typ=None):
131 PProtocol.__init__(self, name, typ=typ)
134 def default(self, obj, typ):
137 for type_permis in typ:
138 if type_permis == 'R':
139 if is_float_or_int(obj):
141 elif type_permis == 'I':
144 elif type_permis == 'C':
145 if self.is_complexe(obj):
147 elif type_permis == 'TXM':
150 elif type_permis == 'shell':
153 elif type_permis == 'Fichier':
155 if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj):
159 ufmt(_(u"%s n'est pas un fichier valide"), repr(obj)))
160 elif type_permis == 'FichierNoAbs':
162 if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")):
166 ufmt(_(u"%s n'est pas un fichier valide"), repr(obj)))
167 elif type_permis == 'Repertoire':
169 if os.path.isdir(obj):
173 ufmt(_(u"%s n'est pas un répertoire valide"), repr(obj)))
174 elif type(type_permis) == types.ClassType or isinstance(type_permis, type):
176 if self.is_object_from(obj, type_permis):
178 except Exception, err:
180 elif type(type_permis) == types.InstanceType or isinstance(type_permis, object):
182 if type_permis.__convert__(obj):
184 except Exception, err:
187 print convert(ufmt(_(u"Type non encore géré %s"), `type_permis`))
189 ufmt(_(u"%s (de type %s) n'est pas d'un type autorisé: %s %s"),
190 repr(obj), type(obj), typ, unicode(err)))
192 def is_complexe(self, valeur):
193 """ Retourne 1 si valeur est un complexe, 0 sinon """
194 if is_number(valeur):
195 # Pour permettre l'utilisation de complexes Python (accepte les
198 elif type(valeur) != tuple:
199 # On n'autorise pas les listes pour les complexes
201 elif len(valeur) != 3:
204 # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
205 # valeur suivie de 2 reels.
206 if valeur[0].strip() in ('RI', 'MP'):
208 v1 = reelProto.adapt(valeur[1]), reelProto.adapt(valeur[2])
215 def is_object_from(self, objet, classe):
217 Retourne 1 si objet est une instance de la classe classe, 0 sinon
219 convert = getattr(classe, '__convert__', None)
220 if convert is not None:
221 # classe verifie les valeurs
225 except ValueError, err:
229 # On accepte les instances de la classe et des classes derivees
230 return isinstance(objet, classe)
232 reelProto = TypeProtocol("reel", typ=('R',))
235 class CardProtocol(PProtocol):
237 """Verificateur de cardinalité """
238 # pas de registre par instance. Registre unique pour toutes les instances
241 def __init__(self, name, min=1, max=1):
242 PProtocol.__init__(self, name, min=min, max=max)
244 def default(self, obj, min, max):
246 if length < min or length > max:
249 _(u"Nombre d'arguments de %s incorrect (min = %s, max = %s)"),
250 repr(obj), min, max))
254 class IntoProtocol(PProtocol):
256 """Verificateur de choix possibles : liste discrète ou intervalle"""
257 # pas de registre par instance. Registre unique pour toutes les instances
260 def __init__(self, name, into=None, val_min='**', val_max='**'):
262 self, name, into=into, val_min=val_min, val_max=val_max)
263 self.val_min = val_min
264 self.val_max = val_max
266 def default(self, obj, into, val_min, val_max):
271 _(u"La valeur : %s ne fait pas partie des choix possibles %s"),
274 # on est dans le cas d'un ensemble continu de valeurs possibles
276 if is_float_or_int(obj):
281 if obj < val_min or obj > val_max:
284 _(u"La valeur : %s est en dehors du domaine de validité [ %s , %s ]"),
285 repr(obj), self.val_min, self.val_max))
290 # exemple de classe pour verificateur de type
291 # on utilise des instances de classe comme type (typ=MinStr(3,6), par
294 def __init__(self, min, max):
298 def __convert__(self, valeur):
299 if is_str(valeur) and self.min <= len(valeur) <= self.max:
303 _(u"%s n'est pas une chaine de longueur comprise entre %s et %s"),
304 valeur, self.min, self.max))
307 return ufmt(_(u"TXM de longueur entre %s et %s"), self.min, self.max)
310 class Valid(PProtocol):
313 Cette classe est la classe mere des validateurs Accas
314 Elle doit etre derivee
315 Elle presente la signature des methodes indispensables pour son bon
316 fonctionnement et dans certains cas leur comportement par défaut.
318 @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
319 @type cata_info: C{string}
323 def __init__(self, **args):
324 PProtocol.__init__(self, "valid", **args)
328 Cette methode retourne une chaine de caractères informative sur
329 la validation demandée par le validateur. Elle est utilisée
330 pour produire le compte-rendu de validité du mot clé associé.
332 return _(u"valeur valide")
336 Cette methode retourne une chaine de caractère qui permet
337 de construire un message d'aide en ligne.
338 En général, le message retourné est le meme que celui retourné par la
343 def info_erreur_item(self):
345 Cette méthode permet d'avoir un message d'erreur pour un item
346 dans une liste dans le cas ou le validateur fait des vérifications
347 sur les items d'une liste. Si le validateur fait seulement des
348 vérifications sur la liste elle meme et non sur ses items, la méthode
349 doit retourner une chaine vide.
353 def info_erreur_liste(self):
355 Cette méthode a un comportement complémentaire de celui de
356 info_erreur_item. Elle retourne un message d'erreur lié uniquement
357 aux vérifications sur la liste elle meme et pas sur ses items.
358 Dans le cas où le validateur ne fait pas de vérification sur des
359 listes, elle retourne une chaine vide
363 def verif(self, valeur):
365 Cette methode sert a verifier si la valeur passee en argument est consideree
366 comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
367 (valide) sinon 0 (invalide).
369 @type valeur: tout type python
370 @param valeur: valeur du mot cle a valider
372 @return: indicateur de validite 1 (valide) ou 0 (invalide)
374 raise NotImplementedError("Must be implemented")
376 def verif_item(self, valeur):
378 La methode verif du validateur effectue une validation complete de
379 la valeur. valeur peut etre un scalaire ou une liste. Le validateur
380 doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
381 methode is_list doit retourner 1).
382 La methode valid_item sert pour effectuer des validations partielles
383 de liste. Elle doit uniquement verifier la validite d'un item de
384 liste mais pas les caracteristiques de la liste.
388 def valide_liste_partielle(self, liste_courante):
390 Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
391 ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
392 veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
394 En général un validateur effectue la meme validation pour les listes partielles et les
397 return self.verif(liste_courante)
399 def verif_cata(self):
401 Cette methode sert a realiser des verifications du validateur lui meme.
402 Elle est facultative et retourne 1 (valide) par defaut.
403 Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
404 parametres de definition ne sont pas corrects.
405 La raison de l'invalidite est stockee dans l'attribut cata_info.
408 @return: indicateur de validite 1 (valide) ou 0 (invalide)
414 Cette méthode retourne un entier qui indique si le validateur
415 permet les listes (valeur 1) ou ne les permet pas (valeur 0).
416 Par défaut, un validateur n'autorise que des scalaires.
422 Cette méthode retourne un entier qui indique si le validateur
423 propose une liste de choix (valeur 1) ou n'en propose pas.
424 Par défaut, un validateur n'en propose pas.
428 def get_into(self, liste_courante=None, into_courant=None):
430 Cette méthode retourne la liste de choix proposée par le validateur.
431 Si le validateur ne propose pas de liste de choix, la méthode
433 L'argument d'entrée liste_courante, s'il est différent de None, donne
434 la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
435 méthode get_into doit calculer la liste des choix en en tenant
436 compte. Par exemple, si le validateur n'autorise pas les répétitions,
437 la liste des choix retournée ne doit pas contenir les choix déjà
438 contenus dans liste_courante.
439 L'argument d'entrée into_courant, s'il est différent de None, donne
440 la liste des choix proposés par d'autres validateurs. Dans ce cas,
441 la méthode get_into doit calculer la liste des choix à retourner
442 en se limitant à cette liste initiale. Par exemple, si into_courant
443 vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
444 la méthode ne doit retourner que (3,).
446 La méthode get_into peut retourner une liste vide [], ce qui veut
447 dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
448 peut etre normale : l''utilisateur a utilisé tous les choix, ou
449 résulter d'une incohérence des validateurs :
450 choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
451 faire la différence entre ces deux situations.
456 class ListVal(Valid):
459 Cette classe sert de classe mère pour tous les validateurs qui acceptent
466 def get_into(self, liste_courante=None, into_courant=None):
468 Cette méthode get_into effectue un traitement général qui consiste
469 a filtrer la liste de choix into_courant, si elle existe, en ne
470 conservant que les valeurs valides (appel de la méthode valid).
472 if into_courant is None:
476 for e in into_courant:
478 liste_choix.append(e)
481 def convert(self, valeur):
483 Méthode convert pour les validateurs de listes. Cette méthode
484 fait appel à la méthode convert_item sur chaque élément de la
487 if is_sequence(valeur):
489 self.convert_item(val)
492 return self.convert_item(valeur)
494 def verif(self, valeur):
496 Méthode verif pour les validateurs de listes. Cette méthode
497 fait appel à la méthode verif_item sur chaque élément de la
498 liste. Si valeur est un paramètre, on utilise sa valeur effective
501 if is_sequence(valeur):
503 if not self.verif_item(val):
507 return self.verif_item(valeur)
510 class Compulsory(ListVal):
512 Validateur operationnel
513 Verification de la présence obligatoire d'un élément dans une liste
517 def __init__(self, elem=()):
518 if not is_sequence(elem):
520 Valid.__init__(self, elem=elem)
525 return ufmt(_(u"valeur %s obligatoire"), `self.elem`)
527 def default(self, valeur, elem):
530 def verif_item(self, valeur):
533 def convert(self, valeur):
534 elem = list(self.elem)
541 ufmt(_(u"%s ne contient pas les elements obligatoires : %s "),
548 def verif(self, valeur):
549 if not is_sequence(valeur):
553 for val in self.elem:
558 def info_erreur_item(self):
559 return _(u"La valeur n'est pas dans la liste des choix possibles")
562 class Together(ListVal):
564 Validateur operationnel
565 si un des éléments est présent les autres doivent aussi l'être
569 def __init__(self, elem=()):
570 if not is_sequence(elem):
572 Valid.__init__(self, elem=elem)
577 return ufmt(_(u"%s présent ensemble"), `self.elem`)
579 def default(self, valeur, elem):
582 def verif_item(self, valeur):
585 def convert(self, valeur):
586 elem = list(self.elem)
589 if v in elem: elem.remove(v)
590 if ( len(elem) == 0 ): return valeur
591 if len(elem) != len(list(self.elem)) :
592 raise ValError( ufmt(_(u"%s ne contient pas les éléments devant être présent ensemble: %s "), valeur, elem))
598 def verif(self, valeur):
599 if not is_sequence(valeur):
604 for val in self.elem:
605 if val in liste: compte += 1
606 if ( compte == 0 ): return 1
607 if ( compte != len( list(self.elem) ) ): return 0
610 def info_erreur_item(self):
611 return _(u"La valeur n'est pas dans la liste des choix possibles")
614 class Absent(ListVal):
616 Validateur operationnel
617 si un des éléments est présent non valide
621 def __init__(self, elem=()):
622 if not is_sequence(elem):
624 Valid.__init__(self, elem=elem)
629 return ufmt(_(u"%s absent"), `self.elem`)
631 def default(self, valeur, elem):
634 def verif_item(self, valeur):
637 def convert(self, valeur):
638 elem = list(self.elem)
642 raise ValError( ufmt(_(u"%s n'est pas autorisé : %s "), v, elem))
648 def verif(self, valeur):
649 if not is_sequence(valeur):
653 for val in self.elem:
654 if val in liste: return 0
657 def info_erreur_item(self):
658 return _(u"La valeur n'est pas dans la liste des choix possibles")
661 class NoRepeat(ListVal):
663 Validateur operationnel
664 Verification d'absence de doublons dans la liste.
671 return _(u": pas de présence de doublon dans la liste")
673 def info_erreur_liste(self):
674 return _(u"Les doublons ne sont pas permis")
676 def default(self, valeur):
677 if valeur in self.liste:
678 raise ValError(ufmt(_(u"%s est un doublon"), valeur))
681 def convert(self, valeur):
688 def verif_item(self, valeur):
691 def verif(self, valeur):
692 if is_sequence(valeur):
695 if liste.count(val) != 1:
701 def get_into(self, liste_courante=None, into_courant=None):
703 Methode get_into spécifique pour validateur NoRepeat, on retourne
704 une liste de choix qui ne contient aucune valeur de into_courant
705 déjà contenue dans liste_courante
707 if into_courant is None:
711 for e in into_courant:
714 if liste_courante is not None and e in liste_courante:
716 liste_choix.append(e)
720 class LongStr(ListVal):
723 Validateur operationnel
724 Verification de la longueur d une chaine
727 def __init__(self, low, high):
728 ListVal.__init__(self, low=low, high=high)
734 return ufmt(_(u"longueur de la chaine entre %s et %s"), self.low, self.high)
736 def info_erreur_item(self):
737 return _(u"Longueur de la chaine incorrecte")
739 def convert(self, valeur):
744 def verif_item(self, valeur):
751 def default(self, valeur, low, high):
752 if not is_str(valeur):
753 raise ValError(ufmt(_(u"%s n'est pas une chaine"), repr(valeur)))
754 if valeur[0] == "'" and valeur[-1] == "'":
757 if len(valeur) < low or len(valeur) > high:
759 ufmt(_(u"%s n'est pas de la bonne longueur"), repr(valeur)))
763 class OnlyStr(ListVal):
766 Validateur operationnel
767 Valide que c'est une chaine
771 ListVal.__init__(self)
775 return _(u"regarde si c'est une chaine")
777 def info_erreur_item(self):
778 return _(u"Ce n'est pas une chaine")
780 def convert(self, valeur):
785 def verif_item(self, valeur):
792 def default(self, valeur):
793 if not is_str(valeur):
794 raise ValError(ufmt(_(u"%s n'est pas une chaine"), repr(valeur)))
798 class OrdList(ListVal):
801 Validateur operationnel
802 Verification qu'une liste est croissante ou decroissante
805 def __init__(self, ord):
806 ListVal.__init__(self, ord=ord)
811 return ufmt(_(u"liste %s"), self.ord)
813 def info_erreur_liste(self):
814 return ufmt(_(u"La liste doit etre en ordre %s"), self.ord)
816 def convert(self, valeur):
823 def default(self, valeur, ord):
824 if self.ord == 'croissant':
825 if self.val is not None and valeur < self.val:
827 ufmt(_(u"%s n'est pas par valeurs croissantes"), repr(self.liste)))
828 elif self.ord == 'decroissant':
829 if self.val is not None and valeur > self.val:
831 ufmt(_(u"%s n'est pas par valeurs decroissantes"), repr(self.liste)))
835 def verif_item(self, valeur):
838 def get_into(self, liste_courante=None, into_courant=None):
840 Methode get_into spécifique pour validateur OrdList, on retourne
841 une liste de choix qui ne contient aucune valeur de into_courant
842 dont la valeur est inférieure à la dernière valeur de
843 liste_courante, si elle est différente de None.
845 if into_courant is None:
847 elif not liste_courante:
851 last_val = liste_choix[-1]
852 for e in into_courant:
853 if self.ord == 'croissant' and e <= last_val:
855 if self.ord == 'decroissant' and e >= last_val:
857 liste_choix.append(e)
864 Validateur operationnel
865 Cette classe est un validateur qui controle une liste de validateurs
866 Elle verifie qu'au moins un des validateurs de la liste valide la valeur
869 def __init__(self, validators=()):
870 if not is_sequence(validators):
871 validators = (validators,)
873 for validator in validators:
874 if type(validator) == types.FunctionType:
875 self.validators.append(FunctionVal(validator))
877 self.validators.append(validator)
881 return "\n ou ".join([v.info() for v in self.validators])
883 def convert(self, valeur):
884 for validator in self.validators:
886 return validator.convert(valeur)
889 raise ValError(ufmt(_(u"%s n'est pas du bon type"), repr(valeur)))
891 def info_erreur_item(self):
893 for v in self.validators:
894 err = v.info_erreur_item()
897 chaine = " \n ou ".join(l)
900 def info_erreur_liste(self):
902 for v in self.validators:
903 err = v.info_erreur_liste()
906 chaine = " \n ou ".join(l)
911 Si plusieurs validateurs sont reliés par un OU
912 il suffit qu'un seul des validateurs attende une liste
913 pour qu'on considère que leur union attend une liste.
915 for validator in self.validators:
916 v = validator.is_list()
921 def verif(self, valeur):
922 for validator in self.validators:
923 v = validator.verif(valeur)
928 def verif_item(self, valeur):
929 for validator in self.validators:
930 v = validator.verif_item(valeur)
935 def verif_cata(self):
937 for validator in self.validators:
938 v = validator.verif_cata()
940 infos.append(validator.cata_info)
942 self.cata_info = "\n".join(infos)
949 Dans le cas ou plusieurs validateurs sont reliés par un OU
950 il faut que tous les validateurs proposent un choix pour
951 qu'on considère que leur union propose un choix.
952 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
953 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
955 for validator in self.validators:
956 v = validator.has_into()
961 def get_into(self, liste_courante=None, into_courant=None):
963 Dans le cas ou plusieurs validateurs sont reliés par un OU
964 tous les validateurs doivent proposer un choix pour
965 qu'on considère que leur union propose un choix. Tous les choix
966 proposés par les validateurs sont réunis (opérateur d'union).
967 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
968 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
972 for validator in self.validators:
973 v_into = validator.get_into(liste_courante, into_courant)
976 validator_into.extend(v_into)
977 return validator_into
979 def valide_liste_partielle(self, liste_courante=None):
981 Méthode de validation de liste partielle pour le validateur Or.
982 Si un des validateurs gérés par le validateur Or considère la
983 liste comme valide, le validateur Or la considère comme valide.
985 for validator in self.validators:
986 v = validator.valide_liste_partielle(liste_courante)
995 Validateur operationnel
996 Cette classe est un validateur qui controle une liste de validateurs
997 Elle verifie que tous les validateurs de la liste valident la valeur
1000 def __init__(self, validators=()):
1001 if not is_sequence(validators):
1002 validators = (validators,)
1003 self.validators = []
1004 for validator in validators:
1005 if type(validator) == types.FunctionType:
1006 self.validators.append(FunctionVal(validator))
1008 self.validators.append(validator)
1009 if hasattr(validator, 'fonctions'):
1010 for fonction in validator.fonctions:
1011 f = getattr(validator, fonction)
1012 setattr(self, fonction, f)
1016 return "\n et ".join([v.info() for v in self.validators])
1018 def convert(self, valeur):
1019 for validator in self.validators:
1020 valeur = validator.convert(valeur)
1023 def info_erreur_item(self):
1026 for v in self.validators:
1027 if v.info_erreur_item() != " ":
1029 chaine = v.info_erreur_item()
1032 chaine = chaine + " \n et " + v.info_erreur_item()
1035 def info_erreur_liste(self):
1037 for v in self.validators:
1038 if v.info_erreur_liste() != " ":
1040 chaine = v.info_erreur_liste()
1043 chaine = chaine + " \n et " + v.info_erreur_liste()
1046 def verif(self, valeur):
1047 for validator in self.validators:
1048 v = validator.verif(valeur)
1050 self.local_info = validator.info()
1054 def verif_item(self, valeur):
1055 for validator in self.validators:
1056 v = validator.verif_item(valeur)
1058 # L'info n'est probablement pas la meme que pour verif ???
1059 self.local_info = validator.info()
1063 def verif_cata(self):
1065 for validator in self.validators:
1066 v = validator.verif_cata()
1068 infos.append(validator.cata_info)
1070 self.cata_info = "\n".join(infos)
1075 def valide_liste_partielle(self, liste_courante=None):
1077 Méthode de validation de liste partielle pour le validateur And.
1078 Tous les validateurs gérés par le validateur And doivent considérer
1079 la liste comme valide, pour que le validateur And la considère
1082 for validator in self.validators:
1083 v = validator.valide_liste_partielle(liste_courante)
1090 Si plusieurs validateurs sont reliés par un ET
1091 il faut que tous les validateurs attendent une liste
1092 pour qu'on considère que leur intersection attende une liste.
1093 Exemple Range(2,5) ET Card(1) n'attend pas une liste
1094 Range(2,5) ET Pair attend une liste
1096 for validator in self.validators:
1097 v = validator.is_list()
1104 Dans le cas ou plusieurs validateurs sont reliés par un ET
1105 il suffit qu'un seul validateur propose un choix pour
1106 qu'on considère que leur intersection propose un choix.
1107 Exemple : Enum(1,2,3) ET entier pair, propose un choix
1108 En revanche, entier pair ET superieur à 10 ne propose pas de choix
1110 for validator in self.validators:
1111 v = validator.has_into()
1116 def get_into(self, liste_courante=None, into_courant=None):
1118 Dans le cas ou plusieurs validateurs sont reliés par un ET
1119 il suffit qu'un seul validateur propose un choix pour
1120 qu'on considère que leur intersection propose un choix. Tous les
1121 choix proposés par les validateurs sont croisés (opérateur
1123 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
1124 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
1126 for validator in self.validators:
1127 into_courant = validator.get_into(liste_courante, into_courant)
1128 if into_courant in ([], None):
1133 def do_liste(validators):
1135 Convertit une arborescence de validateurs en OrVal ou AndVal
1136 validators est une liste de validateurs ou de listes ou de tuples
1139 for validator in validators:
1140 if type(validator) == types.FunctionType:
1141 valids.append(FunctionVal(validator))
1142 elif type(validator) is tuple:
1143 valids.append(OrVal(do_liste(validator)))
1144 elif type(validator) is list:
1145 valids.append(AndVal(do_liste(validator)))
1147 valids.append(validator)
1151 def validatorFactory(validator):
1152 if type(validator) == types.FunctionType:
1153 return FunctionVal(validator)
1154 elif type(validator) is tuple:
1155 return OrVal(do_liste(validator))
1156 elif type(validator) is list:
1157 return AndVal(do_liste(validator))
1161 # Ci-dessous : exemples de validateur (peu testés)
1164 class RangeVal(ListVal):
1167 Exemple de classe validateur : verification qu'une valeur
1168 est dans un intervalle.
1169 Pour une liste on verifie que tous les elements sont
1171 Susceptible de remplacer les attributs "vale_min" "vale_max"
1175 def __init__(self, low, high):
1178 self.cata_info = ufmt(_(u"%s doit être inférieur a %s"), low, high)
1181 return ufmt(_(u"valeur dans l'intervalle %s , %s"), self.low, self.high)
1183 def convert_item(self, valeur):
1184 if valeur > self.low and valeur < self.high:
1186 raise ValError(ufmt(_(u"%s devrait être comprise entre %s et %s"),
1187 valeur, self.low, self.high))
1189 def verif_item(self, valeur):
1190 return valeur > self.low and valeur < self.high
1192 def info_erreur_item(self):
1193 return ufmt(_(u"La valeur doit etre comprise entre %s et %s"), self.low, self.high)
1195 def verif_cata(self):
1196 if self.low > self.high:
1201 class CardVal(Valid):
1204 Exemple de classe validateur : verification qu'une liste est
1205 d'une longueur superieur a un minimum (min) et inferieure
1207 Susceptible de remplacer les attributs "min" "max" dans les
1211 def __init__(self, min='**', max='**'):
1214 self.cata_info = ufmt(_(u"%s doit etre inferieur a %s"), min, max)
1217 return ufmt(_(u"longueur de liste comprise entre %s et %s"), self.min, self.max)
1219 def info_erreur_liste(self):
1221 _(u"Le cardinal de la liste doit etre compris entre %s et %s"),
1225 return self.max == '**' or self.max > 1
1227 def get_into(self, liste_courante=None, into_courant=None):
1228 if into_courant is None:
1230 elif liste_courante is None:
1232 elif self.max == '**':
1234 elif len(liste_courante) < self.max:
1239 def convert(self, valeur):
1240 if is_sequence(valeur):
1242 elif valeur is None:
1246 if self.max != '**' and l > self.max:
1248 ufmt(_(u"%s devrait etre de longueur inferieure a %s"), valeur, self.max))
1249 if self.min != '**' and l < self.min:
1251 ufmt(_(u"%s devrait etre de longueur superieure a %s"), valeur, self.min))
1254 def verif_item(self, valeur):
1257 def verif(self, valeur):
1258 if is_sequence(valeur):
1259 if self.max != '**' and len(valeur) > self.max:
1261 if self.min != '**' and len(valeur) < self.min:
1265 if self.max != '**' and 1 > self.max:
1267 if self.min != '**' and 1 < self.min:
1271 def verif_cata(self):
1272 if self.min != '**' and self.max != '**' and self.min > self.max:
1276 def valide_liste_partielle(self, liste_courante=None):
1278 if liste_courante != None:
1279 if len(liste_courante) > self.max:
1284 class PairVal(ListVal):
1287 Exemple de classe validateur : verification qu'une valeur
1289 Pour une liste on verifie que tous les elements sont
1294 ListVal.__init__(self)
1298 return _(u"valeur paire")
1300 def info_erreur_item(self):
1301 return _(u"La valeur saisie doit etre paire")
1303 def convert(self, valeur):
1308 ufmt(_(u"%s contient des valeurs non paires"), repr(valeur)))
1311 def default(self, valeur):
1314 def verif_item(self, valeur):
1315 if type(valeur) not in (int, long):
1317 return valeur % 2 == 0
1319 def verif(self, valeur):
1320 if is_sequence(valeur):
1331 class EnumVal(ListVal):
1334 Exemple de classe validateur : verification qu'une valeur
1335 est prise dans une liste de valeurs.
1336 Susceptible de remplacer l attribut "into" dans les catalogues
1339 def __init__(self, into=()):
1340 if not is_sequence(into):
1346 return "valeur dans %s" % `self.into`
1348 def convert_item(self, valeur):
1349 if valeur in self.into:
1352 ufmt(_(u"%s contient des valeurs hors des choix possibles: %s "),
1355 def verif_item(self, valeur):
1356 if valeur not in self.into:
1363 def get_into(self, liste_courante=None, into_courant=None):
1364 if into_courant is None:
1365 liste_choix = list(self.into)
1368 for e in into_courant:
1370 liste_choix.append(e)
1373 def info_erreur_item(self):
1374 return _(u"La valeur n'est pas dans la liste des choix possibles")
1377 def ImpairVal(valeur):
1379 Exemple de validateur
1380 Cette fonction est un validateur. Elle verifie que la valeur passee
1381 est bien un nombre impair.
1383 if is_sequence(valeur):
1393 ImpairVal.info = "valeur impaire"
1399 Exemple de validateur
1400 Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1401 que la somme des cles A et B vaut une valeur donnee
1402 en parametre du validateur
1405 def __init__(self, somme=10):
1410 return ufmt(_(u"valeur %s pour la somme des cles A et B "), self.somme)
1412 def verif(self, valeur):
1413 if is_sequence(valeur):
1415 if not val.has_key("A"):
1417 if not val.has_key("B"):
1419 if val["A"] + val["B"] != self.somme:
1423 if not valeur.has_key("A"):
1425 if not valeur.has_key("B"):
1427 if valeur["A"] + valeur["B"] != self.somme:
1432 class FunctionVal(Valid):
1435 Exemple de validateur
1436 Cette classe est un validateur qui est initialise avec une fonction
1439 def __init__(self, function):
1440 self.function = function
1443 return self.function.info
1445 def verif(self, valeur):
1446 return self.function(valeur)
1448 def verif_item(self, valeur):
1449 return self.function(valeur)
1451 def convert(self, valeur):
1454 # MC ca ne devrait plus servir !
1455 CoercableFuncs = {types.IntType: int,
1456 types.LongType: long,
1457 types.FloatType: float,
1458 types.ComplexType: complex,
1459 types.UnicodeType: unicode}
1462 class TypeVal(ListVal):
1465 Exemple de validateur
1466 Cette classe est un validateur qui controle qu'une valeur
1467 est bien du type Python attendu.
1468 Pour une liste on verifie que tous les elements sont du bon type.
1469 Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1470 alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1473 def __init__(self, aType):
1474 # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1475 # type(1) == int;type(0.2)==float;etc.
1476 if type(aType) != types.TypeType:
1480 self.coerce = CoercableFuncs[aType]
1482 self.coerce = self.identity
1485 return ufmt(_(u"valeur de %s"), self.aType)
1487 def identity(self, value):
1488 if type(value) == self.aType:
1492 def convert_item(self, valeur):
1493 return self.coerce(valeur)
1495 def verif_item(self, valeur):
1503 class InstanceVal(ListVal):
1506 Exemple de validateur
1507 Cette classe est un validateur qui controle qu'une valeur est
1508 bien une instance (au sens Python) d'une classe
1509 Pour une liste on verifie chaque element de la liste
1512 def __init__(self, aClass):
1513 # Si aClass est une classe on la memorise dans self.aClass
1514 # sinon c'est une instance dont on memorise la classe
1515 if type(aClass) == types.InstanceType:
1516 # instance ancienne mode
1517 aClass = aClass.__class__
1518 elif type(aClass) == types.ClassType:
1519 # classe ancienne mode
1521 elif type(aClass) == type:
1522 # classe nouvelle mode
1524 elif isinstance(aClass, object):
1525 # instance nouvelle mode
1526 aClass = type(aClass)
1528 raise ValError(_(u"type non supporté"))
1530 self.aClass = aClass
1533 return ufmt(_(u"valeur d'instance de %s"), self.aClass.__name__)
1535 def verif_item(self, valeur):
1536 if not isinstance(valeur, self.aClass):
1541 class VerifTypeTuple(Valid, ListVal):
1543 def __init__(self, typeDesTuples):
1544 self.typeDesTuples = typeDesTuples
1545 Valid.__init__(self)
1549 return _(u": vérifie les types dans un tuple")
1551 def info_erreur_liste(self):
1552 return _(u"Les types entrés ne sont pas permis")
1554 def default(self, valeur):
1555 # if valeur in self.liste : raise ValError("%s est un doublon" %
1562 def convert_item(self, valeur):
1563 if len(valeur) != len(self.typeDesTuples):
1565 ufmt(_(u"%s devrait etre de type %s "), valeur, self.typeDesTuples))
1566 for i in range(len(valeur)):
1567 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1570 ufmt(_(u"%s devrait etre de type %s "), valeur, self.typeDesTuples))
1573 def verif_item(self, valeur):
1575 if len(valeur) != len(self.typeDesTuples):
1577 for i in range(len(valeur)):
1578 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1585 def verifType(self, valeur, type_permis):
1586 if type_permis == 'R':
1587 if type(valeur) in (types.IntType, types.FloatType, types.LongType):
1589 elif type_permis == 'I':
1590 if type(valeur) in (types.IntType, types.LongType):
1592 elif type_permis == 'C':
1593 if self.is_complexe(valeur):
1595 elif type_permis == 'TXM':
1596 if type(valeur) == types.StringType:
1600 def verif(self, valeur):
1601 if type(valeur) in (types.ListType, types.TupleType):
1602 liste = list(valeur)
1604 if self.verif_item(val) != 1:
1609 class VerifExiste(ListVal):
1612 fonctionne avec into
1613 Met une liste à jour selon les mot clefs existant
1614 exemple si into = ("A","B","C")
1615 si au niveau N du JDC les objets "A" et "C" existe
1616 alors la liste des into deviendra ( "A","C")
1618 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1619 niveauVerif est defini par rapport au Noeud :
1620 exemple niveauVerif = 1 : on verifie les freres
1621 niveauVerif = 2 : on verifie les oncles..
1624 def __init__(self, niveauVerif):
1625 ListVal.__init__(self)
1626 self.niveauVerif = niveauVerif
1628 self.listeDesFreres = ()
1629 self.fonctions = ('verifie_liste', 'set_MCSimp')
1634 def verifie_liste(self, liste):
1635 self.set_MCSimp(self.MCSimp)
1637 if not(item in self.listeDesFreres):
1641 def verif_item(self, valeur):
1642 self.set_MCSimp(self.MCSimp)
1643 if valeur in self.listeDesFreres:
1647 def set_MCSimp(self, MCSimp):
1648 self.MCSimp = MCSimp
1649 k = self.niveauVerif
1655 # on met la liste à jour
1656 parent.forceRecalcul = self.niveauVerif
1657 self.listeDesFreres = parent.liste_mc_presents()
1659 def convert_item(self, valeur):
1660 if valeur in self.listeDesFreres:
1663 ufmt(_(u"%s n'est pas dans %s"), valeur, self.listeDesFreres))
1666 class RegExpVal(ListVal):
1669 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1672 errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1674 def __init__(self, pattern):
1675 self.pattern = pattern
1676 self.compiled_regexp = re.compile(pattern)
1679 return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
1681 def verif_item(self, valeur):
1682 if self.compiled_regexp.match(valeur):
1685 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1687 def convert_item(self, valeur):
1688 if self.compiled_regexp.match(valeur):
1691 raise ValError(self.errormsg %
1692 {"value": valeur, "pattern": self.pattern})
1695 class FileExtVal(RegExpVal):
1698 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1701 def __init__(self, ext):
1703 self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1705 RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
1708 return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext