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):
1038 for v in self.validators:
1039 if v.info_erreur_liste() != " ":
1041 chaine = v.info_erreur_liste()
1044 chaine = chaine + " \n et " + v.info_erreur_liste()
1047 def verif(self, valeur):
1048 for validator in self.validators:
1049 v = validator.verif(valeur)
1051 self.local_info = validator.info()
1055 def verif_item(self, valeur):
1056 for validator in self.validators:
1057 v = validator.verif_item(valeur)
1059 # L'info n'est probablement pas la meme que pour verif ???
1060 self.local_info = validator.info()
1064 def verif_cata(self):
1066 for validator in self.validators:
1067 v = validator.verif_cata()
1069 infos.append(validator.cata_info)
1071 self.cata_info = "\n".join(infos)
1076 def valide_liste_partielle(self, liste_courante=None):
1078 Méthode de validation de liste partielle pour le validateur And.
1079 Tous les validateurs gérés par le validateur And doivent considérer
1080 la liste comme valide, pour que le validateur And la considère
1083 for validator in self.validators:
1084 v = validator.valide_liste_partielle(liste_courante)
1091 Si plusieurs validateurs sont reliés par un ET
1092 il faut que tous les validateurs attendent une liste
1093 pour qu'on considère que leur intersection attende une liste.
1094 Exemple Range(2,5) ET Card(1) n'attend pas une liste
1095 Range(2,5) ET Pair attend une liste
1097 for validator in self.validators:
1098 v = validator.is_list()
1105 Dans le cas ou plusieurs validateurs sont reliés par un ET
1106 il suffit qu'un seul validateur propose un choix pour
1107 qu'on considère que leur intersection propose un choix.
1108 Exemple : Enum(1,2,3) ET entier pair, propose un choix
1109 En revanche, entier pair ET superieur à 10 ne propose pas de choix
1111 for validator in self.validators:
1112 v = validator.has_into()
1117 def get_into(self, liste_courante=None, into_courant=None):
1119 Dans le cas ou plusieurs validateurs sont reliés par un ET
1120 il suffit qu'un seul validateur propose un choix pour
1121 qu'on considère que leur intersection propose un choix. Tous les
1122 choix proposés par les validateurs sont croisés (opérateur
1124 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
1125 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
1127 for validator in self.validators:
1128 into_courant = validator.get_into(liste_courante, into_courant)
1129 if into_courant in ([], None):
1134 def do_liste(validators):
1136 Convertit une arborescence de validateurs en OrVal ou AndVal
1137 validators est une liste de validateurs ou de listes ou de tuples
1140 for validator in validators:
1141 if type(validator) == types.FunctionType:
1142 valids.append(FunctionVal(validator))
1143 elif type(validator) is tuple:
1144 valids.append(OrVal(do_liste(validator)))
1145 elif type(validator) is list:
1146 valids.append(AndVal(do_liste(validator)))
1148 valids.append(validator)
1152 def validatorFactory(validator):
1153 if type(validator) == types.FunctionType:
1154 return FunctionVal(validator)
1155 elif type(validator) is tuple:
1156 return OrVal(do_liste(validator))
1157 elif type(validator) is list:
1158 return AndVal(do_liste(validator))
1162 # Ci-dessous : exemples de validateur (peu testés)
1165 class RangeVal(ListVal):
1168 Exemple de classe validateur : verification qu'une valeur
1169 est dans un intervalle.
1170 Pour une liste on verifie que tous les elements sont
1172 Susceptible de remplacer les attributs "vale_min" "vale_max"
1176 def __init__(self, low, high):
1179 self.cata_info = ufmt(_(u"%s doit être inférieur a %s"), low, high)
1182 return ufmt(_(u"valeur dans l'intervalle %s , %s"), self.low, self.high)
1184 def convert_item(self, valeur):
1185 if valeur > self.low and valeur < self.high:
1187 raise ValError(ufmt(_(u"%s devrait être comprise entre %s et %s"),
1188 valeur, self.low, self.high))
1190 def verif_item(self, valeur):
1191 return valeur > self.low and valeur < self.high
1193 def info_erreur_item(self):
1194 return ufmt(_(u"La valeur doit etre comprise entre %s et %s"), self.low, self.high)
1196 def verif_cata(self):
1197 if self.low > self.high:
1202 class CardVal(Valid):
1205 Exemple de classe validateur : verification qu'une liste est
1206 d'une longueur superieur a un minimum (min) et inferieure
1208 Susceptible de remplacer les attributs "min" "max" dans les
1212 def __init__(self, min='**', max='**'):
1215 self.cata_info = ufmt(_(u"%s doit etre inferieur a %s"), min, max)
1218 return ufmt(_(u"longueur de liste comprise entre %s et %s"), self.min, self.max)
1220 def info_erreur_liste(self):
1222 _(u"Le cardinal de la liste doit etre compris entre %s et %s"),
1226 return self.max == '**' or self.max > 1
1228 def get_into(self, liste_courante=None, into_courant=None):
1229 if into_courant is None:
1231 elif liste_courante is None:
1233 elif self.max == '**':
1235 elif len(liste_courante) < self.max:
1240 def convert(self, valeur):
1241 if is_sequence(valeur):
1243 elif valeur is None:
1247 if self.max != '**' and l > self.max:
1249 ufmt(_(u"%s devrait etre de longueur inferieure a %s"), valeur, self.max))
1250 if self.min != '**' and l < self.min:
1252 ufmt(_(u"%s devrait etre de longueur superieure a %s"), valeur, self.min))
1255 def verif_item(self, valeur):
1258 def verif(self, valeur):
1259 if is_sequence(valeur):
1260 if self.max != '**' and len(valeur) > self.max:
1262 if self.min != '**' and len(valeur) < self.min:
1266 if self.max != '**' and 1 > self.max:
1268 if self.min != '**' and 1 < self.min:
1272 def verif_cata(self):
1273 if self.min != '**' and self.max != '**' and self.min > self.max:
1277 def valide_liste_partielle(self, liste_courante=None):
1279 if liste_courante != None:
1280 if len(liste_courante) > self.max:
1285 class PairVal(ListVal):
1288 Exemple de classe validateur : verification qu'une valeur
1290 Pour une liste on verifie que tous les elements sont
1295 ListVal.__init__(self)
1299 return _(u"valeur paire")
1301 def info_erreur_item(self):
1302 return _(u"La valeur saisie doit etre paire")
1304 def convert(self, valeur):
1309 ufmt(_(u"%s contient des valeurs non paires"), repr(valeur)))
1312 def default(self, valeur):
1315 def verif_item(self, valeur):
1316 if type(valeur) not in (int, long):
1318 return valeur % 2 == 0
1320 def verif(self, valeur):
1321 if is_sequence(valeur):
1332 class EnumVal(ListVal):
1335 Exemple de classe validateur : verification qu'une valeur
1336 est prise dans une liste de valeurs.
1337 Susceptible de remplacer l attribut "into" dans les catalogues
1340 def __init__(self, into=()):
1341 if not is_sequence(into):
1347 return "valeur dans %s" % `self.into`
1349 def convert_item(self, valeur):
1350 if valeur in self.into:
1353 ufmt(_(u"%s contient des valeurs hors des choix possibles: %s "),
1356 def verif_item(self, valeur):
1357 if valeur not in self.into:
1364 def get_into(self, liste_courante=None, into_courant=None):
1365 if into_courant is None:
1366 liste_choix = list(self.into)
1369 for e in into_courant:
1371 liste_choix.append(e)
1374 def info_erreur_item(self):
1375 return _(u"La valeur n'est pas dans la liste des choix possibles")
1378 def ImpairVal(valeur):
1380 Exemple de validateur
1381 Cette fonction est un validateur. Elle verifie que la valeur passee
1382 est bien un nombre impair.
1384 if is_sequence(valeur):
1394 ImpairVal.info = "valeur impaire"
1400 Exemple de validateur
1401 Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1402 que la somme des cles A et B vaut une valeur donnee
1403 en parametre du validateur
1406 def __init__(self, somme=10):
1411 return ufmt(_(u"valeur %s pour la somme des cles A et B "), self.somme)
1413 def verif(self, valeur):
1414 if is_sequence(valeur):
1416 if not val.has_key("A"):
1418 if not val.has_key("B"):
1420 if val["A"] + val["B"] != self.somme:
1424 if not valeur.has_key("A"):
1426 if not valeur.has_key("B"):
1428 if valeur["A"] + valeur["B"] != self.somme:
1433 class FunctionVal(Valid):
1436 Exemple de validateur
1437 Cette classe est un validateur qui est initialise avec une fonction
1440 def __init__(self, function):
1441 self.function = function
1444 return self.function.info
1446 def verif(self, valeur):
1447 return self.function(valeur)
1449 def verif_item(self, valeur):
1450 return self.function(valeur)
1452 def convert(self, valeur):
1455 # MC ca ne devrait plus servir !
1456 CoercableFuncs = {types.IntType: int,
1457 types.LongType: long,
1458 types.FloatType: float,
1459 types.ComplexType: complex,
1460 types.UnicodeType: unicode}
1463 class TypeVal(ListVal):
1466 Exemple de validateur
1467 Cette classe est un validateur qui controle qu'une valeur
1468 est bien du type Python attendu.
1469 Pour une liste on verifie que tous les elements sont du bon type.
1470 Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1471 alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1474 def __init__(self, aType):
1475 # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1476 # type(1) == int;type(0.2)==float;etc.
1477 if type(aType) != types.TypeType:
1481 self.coerce = CoercableFuncs[aType]
1483 self.coerce = self.identity
1486 return ufmt(_(u"valeur de %s"), self.aType)
1488 def identity(self, value):
1489 if type(value) == self.aType:
1493 def convert_item(self, valeur):
1494 return self.coerce(valeur)
1496 def verif_item(self, valeur):
1504 class InstanceVal(ListVal):
1507 Exemple de validateur
1508 Cette classe est un validateur qui controle qu'une valeur est
1509 bien une instance (au sens Python) d'une classe
1510 Pour une liste on verifie chaque element de la liste
1513 def __init__(self, aClass):
1514 # Si aClass est une classe on la memorise dans self.aClass
1515 # sinon c'est une instance dont on memorise la classe
1516 if type(aClass) == types.InstanceType:
1517 # instance ancienne mode
1518 aClass = aClass.__class__
1519 elif type(aClass) == types.ClassType:
1520 # classe ancienne mode
1522 elif type(aClass) == type:
1523 # classe nouvelle mode
1525 elif isinstance(aClass, object):
1526 # instance nouvelle mode
1527 aClass = type(aClass)
1529 raise ValError(_(u"type non supporté"))
1531 self.aClass = aClass
1534 return ufmt(_(u"valeur d'instance de %s"), self.aClass.__name__)
1536 def verif_item(self, valeur):
1537 if not isinstance(valeur, self.aClass):
1542 class VerifTypeTuple(Valid, ListVal):
1544 def __init__(self, typeDesTuples):
1545 self.typeDesTuples = typeDesTuples
1546 Valid.__init__(self)
1550 return _(u": vérifie les types dans un tuple")
1552 def info_erreur_liste(self):
1553 return _(u"Les types entrés ne sont pas permis")
1555 def default(self, valeur):
1556 # if valeur in self.liste : raise ValError("%s est un doublon" %
1563 def convert_item(self, valeur):
1564 if len(valeur) != len(self.typeDesTuples):
1566 ufmt(_(u"%s devrait etre de type %s "), valeur, self.typeDesTuples))
1567 for i in range(len(valeur)):
1568 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1571 ufmt(_(u"%s devrait etre de type %s "), valeur, self.typeDesTuples))
1574 def verif_item(self, valeur):
1576 if len(valeur) != len(self.typeDesTuples):
1578 for i in range(len(valeur)):
1579 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1586 def verifType(self, valeur, type_permis):
1587 if type_permis == 'R':
1588 if type(valeur) in (types.IntType, types.FloatType, types.LongType):
1590 elif type_permis == 'I':
1591 if type(valeur) in (types.IntType, types.LongType):
1593 elif type_permis == 'C':
1594 if self.is_complexe(valeur):
1596 elif type_permis == 'TXM':
1597 if type(valeur) == types.StringType:
1601 def verif(self, valeur):
1602 if type(valeur) in (types.ListType, types.TupleType):
1603 liste = list(valeur)
1605 if self.verif_item(val) != 1:
1610 class VerifExiste(ListVal):
1613 fonctionne avec into
1614 Met une liste à jour selon les mot clefs existant
1615 exemple si into = ("A","B","C")
1616 si au niveau N du JDC les objets "A" et "C" existe
1617 alors la liste des into deviendra ( "A","C")
1619 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1620 niveauVerif est defini par rapport au Noeud :
1621 exemple niveauVerif = 1 : on verifie les freres
1622 niveauVerif = 2 : on verifie les oncles..
1625 def __init__(self, niveauVerif):
1626 ListVal.__init__(self)
1627 self.niveauVerif = niveauVerif
1629 self.listeDesFreres = ()
1630 self.fonctions = ('verifie_liste', 'set_MCSimp')
1635 def verifie_liste(self, liste):
1636 self.set_MCSimp(self.MCSimp)
1638 if not(item in self.listeDesFreres):
1642 def verif_item(self, valeur):
1643 self.set_MCSimp(self.MCSimp)
1644 if valeur in self.listeDesFreres:
1648 def set_MCSimp(self, MCSimp):
1649 self.MCSimp = MCSimp
1650 k = self.niveauVerif
1656 # on met la liste à jour
1657 parent.forceRecalcul = self.niveauVerif
1658 self.listeDesFreres = parent.liste_mc_presents()
1660 def convert_item(self, valeur):
1661 if valeur in self.listeDesFreres:
1664 ufmt(_(u"%s n'est pas dans %s"), valeur, self.listeDesFreres))
1667 class RegExpVal(ListVal):
1670 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1673 errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1675 def __init__(self, pattern):
1676 self.pattern = pattern
1677 self.compiled_regexp = re.compile(pattern)
1680 return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
1682 def verif_item(self, valeur):
1683 if self.compiled_regexp.match(valeur):
1686 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1688 def convert_item(self, valeur):
1689 if self.compiled_regexp.match(valeur):
1692 raise ValError(self.errormsg %
1693 {"value": valeur, "pattern": self.pattern})
1696 class FileExtVal(RegExpVal):
1699 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1702 def __init__(self, ext):
1704 self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1706 #RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
1707 #PNPN Modif pour Adao
1708 #RegExpVal.__init__(self, "^[\S]+\.%s$" % self.ext
1709 RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
1713 return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext