2 # Copyright (C) 2007-2013 EDF R&D
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
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 from Extensions.i18n import tr
38 class ValError(Exception):
43 if hasattr(cls, "__mro__"):
46 for base in cls.__bases__:
47 mro.extend(cls_mro(base))
53 def __init__(self, name):
58 def register(self, T, A):
62 # (a) verifier si l'objet peut s'adapter au protocole
63 adapt = getattr(obj, '__adapt__', None)
65 # on demande à l'objet obj de réaliser lui-meme l'adaptation
68 # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
70 for T in cls_mro(obj.__class__):
71 if T in self.registry:
72 return self.registry[T](obj, self, **self.args)
74 # (c) utiliser l'adapteur par defaut
75 return self.default(obj, **self.args)
77 def default(self, obj, **args):
78 raise TypeError("Can't adapt %s to %s" %
79 (obj.__class__.__name__, self.name))
82 class PProtocol(Protocol):
84 """Verificateur de protocole paramétré (classe de base)"""
85 # Protocole paramétré. Le registre est unique pour toutes les instances.
86 # La methode register est une methode de classe
89 def __init__(self, name, **args):
93 def register(cls, T, A):
95 register = classmethod(register)
98 class ListProtocol(Protocol):
100 """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
102 def default(self, obj):
103 if type(obj) is tuple:
104 if len(obj) > 0 and obj[0] in ('RI', 'MP'):
105 # il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
109 elif type(obj) is list:
112 # pas de valeur affecte. La cardinalite vaut 0
115 # il s'agit d'une chaine. La cardinalite vaut 1
119 # si l'objet supporte len, on a la cardinalite
126 listProto = ListProtocol("list")
129 class TypeProtocol(PProtocol):
131 """Verificateur de type parmi une liste de types possibles"""
132 # pas de registre par instance. Registre unique pour toutes les instances
136 def __init__(self, name, typ=None):
137 PProtocol.__init__(self, name, typ=typ)
140 def default(self, obj, typ):
143 for type_permis in typ:
144 if type_permis == 'R':
145 if is_float_or_int(obj):
147 elif type_permis == 'I':
150 elif type_permis == 'C':
151 if self.is_complexe(obj):
153 elif type_permis == 'TXM':
156 elif type_permis == 'shell':
159 elif type_permis == 'Fichier':
161 if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj):
165 ufmt(_(tr(u"%s n'est pas un fichier valide")), repr(obj)))
166 elif type_permis == 'FichierNoAbs':
168 if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")):
172 ufmt(_(tr(u"%s n'est pas un fichier valide")), repr(obj)))
173 elif type_permis == 'Repertoire':
175 if os.path.isdir(obj):
179 ufmt(_(tr(u"%s n'est pas un répertoire valide")), repr(obj)))
180 elif type(type_permis) == types.ClassType or isinstance(type_permis, type):
182 if self.is_object_from(obj, type_permis):
184 except Exception, err:
186 elif type(type_permis) == types.InstanceType or isinstance(type_permis, object):
188 if type_permis.__convert__(obj):
190 except Exception, err:
193 print convert(ufmt(_(u"Type non encore géré %s"), `type_permis`))
195 ufmt(_(u"%s (de type %s) n'est pas d'un type autorisé: %s %s"),
196 repr(obj), type(obj), typ, unicode(err)))
198 def is_complexe(self, valeur):
199 """ Retourne 1 si valeur est un complexe, 0 sinon """
200 if is_number(valeur):
201 # Pour permettre l'utilisation de complexes Python (accepte les
204 elif type(valeur) != tuple:
205 # On n'autorise pas les listes pour les complexes
207 elif len(valeur) != 3:
210 # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
211 # valeur suivie de 2 reels.
212 if valeur[0].strip() in ('RI', 'MP'):
214 v1 = reelProto.adapt(valeur[1]), reelProto.adapt(valeur[2])
221 def is_object_from(self, objet, classe):
223 Retourne 1 si objet est une instance de la classe classe, 0 sinon
225 convert = getattr(classe, '__convert__', None)
226 if convert is not None:
227 # classe verifie les valeurs
231 except ValueError, err:
235 # On accepte les instances de la classe et des classes derivees
236 return isinstance(objet, classe)
238 reelProto = TypeProtocol("reel", typ=('R',))
241 class CardProtocol(PProtocol):
243 """Verificateur de cardinalité """
244 # pas de registre par instance. Registre unique pour toutes les instances
247 def __init__(self, name, min=1, max=1):
248 PProtocol.__init__(self, name, min=min, max=max)
250 def default(self, obj, min, max):
252 if length < min or length > max:
255 _(tr(u"Nombre d'arguments de %s incorrect (min = %s, max = %s)")),
256 repr(obj), min, max))
260 class IntoProtocol(PProtocol):
262 """Verificateur de choix possibles : liste discrète ou intervalle"""
263 # pas de registre par instance. Registre unique pour toutes les instances
266 def __init__(self, name, into=None, val_min='**', val_max='**'):
268 self, name, into=into, val_min=val_min, val_max=val_max)
269 self.val_min = val_min
270 self.val_max = val_max
272 def default(self, obj, into, val_min, val_max):
277 _tr((u"La valeur : %s ne fait pas partie des choix possibles %s")),
280 # on est dans le cas d'un ensemble continu de valeurs possibles
282 if is_float_or_int(obj):
287 if obj < val_min or obj > val_max:
290 _(tr(u"La valeur : %s est en dehors du domaine de validité [ %s , %s ]")),
291 repr(obj), self.val_min, self.val_max))
296 # exemple de classe pour verificateur de type
297 # on utilise des instances de classe comme type (typ=MinStr(3,6), par
300 def __init__(self, min, max):
304 def __convert__(self, valeur):
305 if is_str(valeur) and self.min <= len(valeur) <= self.max:
309 _tr((u"%s n'est pas une chaine de longueur comprise entre %s et %s")),
310 valeur, self.min, self.max))
313 return ufmt(_(u"TXM de longueur entre %s et %s"), self.min, self.max)
316 class Valid(PProtocol):
319 Cette classe est la classe mere des validateurs Accas
320 Elle doit etre derivee
321 Elle presente la signature des methodes indispensables pour son bon
322 fonctionnement et dans certains cas leur comportement par défaut.
324 @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
325 @type cata_info: C{string}
329 def __init__(self, **args):
330 PProtocol.__init__(self, "valid", **args)
334 Cette methode retourne une chaine de caractères informative sur
335 la validation demandée par le validateur. Elle est utilisée
336 pour produire le compte-rendu de validité du mot clé associé.
338 return _(u"valeur valide")
342 Cette methode retourne une chaine de caractère qui permet
343 de construire un message d'aide en ligne.
344 En général, le message retourné est le meme que celui retourné par la
349 def info_erreur_item(self):
351 Cette méthode permet d'avoir un message d'erreur pour un item
352 dans une liste dans le cas ou le validateur fait des vérifications
353 sur les items d'une liste. Si le validateur fait seulement des
354 vérifications sur la liste elle meme et non sur ses items, la méthode
355 doit retourner une chaine vide.
359 def info_erreur_liste(self):
361 Cette méthode a un comportement complémentaire de celui de
362 info_erreur_item. Elle retourne un message d'erreur lié uniquement
363 aux vérifications sur la liste elle meme et pas sur ses items.
364 Dans le cas où le validateur ne fait pas de vérification sur des
365 listes, elle retourne une chaine vide
369 def verif(self, valeur):
371 Cette methode sert a verifier si la valeur passee en argument est consideree
372 comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
373 (valide) sinon 0 (invalide).
375 @type valeur: tout type python
376 @param valeur: valeur du mot cle a valider
378 @return: indicateur de validite 1 (valide) ou 0 (invalide)
380 raise NotImplementedError("Must be implemented")
382 def verif_item(self, valeur):
384 La methode verif du validateur effectue une validation complete de
385 la valeur. valeur peut etre un scalaire ou une liste. Le validateur
386 doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
387 methode is_list doit retourner 1).
388 La methode valid_item sert pour effectuer des validations partielles
389 de liste. Elle doit uniquement verifier la validite d'un item de
390 liste mais pas les caracteristiques de la liste.
394 def valide_liste_partielle(self, liste_courante):
396 Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
397 ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
398 veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
400 En général un validateur effectue la meme validation pour les listes partielles et les
403 return self.verif(liste_courante)
405 def verif_cata(self):
407 Cette methode sert a realiser des verifications du validateur lui meme.
408 Elle est facultative et retourne 1 (valide) par defaut.
409 Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
410 parametres de definition ne sont pas corrects.
411 La raison de l'invalidite est stockee dans l'attribut cata_info.
414 @return: indicateur de validite 1 (valide) ou 0 (invalide)
420 Cette méthode retourne un entier qui indique si le validateur
421 permet les listes (valeur 1) ou ne les permet pas (valeur 0).
422 Par défaut, un validateur n'autorise que des scalaires.
428 Cette méthode retourne un entier qui indique si le validateur
429 propose une liste de choix (valeur 1) ou n'en propose pas.
430 Par défaut, un validateur n'en propose pas.
434 def get_into(self, liste_courante=None, into_courant=None):
436 Cette méthode retourne la liste de choix proposée par le validateur.
437 Si le validateur ne propose pas de liste de choix, la méthode
439 L'argument d'entrée liste_courante, s'il est différent de None, donne
440 la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
441 méthode get_into doit calculer la liste des choix en en tenant
442 compte. Par exemple, si le validateur n'autorise pas les répétitions,
443 la liste des choix retournée ne doit pas contenir les choix déjà
444 contenus dans liste_courante.
445 L'argument d'entrée into_courant, s'il est différent de None, donne
446 la liste des choix proposés par d'autres validateurs. Dans ce cas,
447 la méthode get_into doit calculer la liste des choix à retourner
448 en se limitant à cette liste initiale. Par exemple, si into_courant
449 vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
450 la méthode ne doit retourner que (3,).
452 La méthode get_into peut retourner une liste vide [], ce qui veut
453 dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
454 peut etre normale : l''utilisateur a utilisé tous les choix, ou
455 résulter d'une incohérence des validateurs :
456 choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
457 faire la différence entre ces deux situations.
462 class ListVal(Valid):
465 Cette classe sert de classe mère pour tous les validateurs qui acceptent
472 def get_into(self, liste_courante=None, into_courant=None):
474 Cette méthode get_into effectue un traitement général qui consiste
475 a filtrer la liste de choix into_courant, si elle existe, en ne
476 conservant que les valeurs valides (appel de la méthode valid).
478 if into_courant is None:
482 for e in into_courant:
484 liste_choix.append(e)
487 def convert(self, valeur):
489 Méthode convert pour les validateurs de listes. Cette méthode
490 fait appel à la méthode convert_item sur chaque élément de la
493 if is_sequence(valeur):
495 self.convert_item(val)
498 return self.convert_item(valeur)
500 def verif(self, valeur):
502 Méthode verif pour les validateurs de listes. Cette méthode
503 fait appel à la méthode verif_item sur chaque élément de la
504 liste. Si valeur est un paramètre, on utilise sa valeur effective
507 if is_sequence(valeur):
509 if not self.verif_item(val):
513 return self.verif_item(valeur)
516 class Compulsory(ListVal):
519 Validateur operationnel
520 Verification de la présence obligatoire d'un élément dans une liste
524 def __init__(self, elem=()):
525 if not is_sequence(elem):
527 Valid.__init__(self, elem=elem)
532 return ufmt(_(u"valeur %s obligatoire"), `self.elem`)
534 def default(self, valeur, elem):
537 def verif_item(self, valeur):
540 def convert(self, valeur):
541 elem = list(self.elem)
548 ufmt(_tr((u"%s ne contient pas les elements obligatoires : %s ")),
555 def verif(self, valeur):
556 if not is_sequence(valeur):
560 for val in self.elem:
565 def info_erreur_item(self):
566 return _(u"La valeur n'est pas dans la liste des choix possibles")
569 class NoRepeat(ListVal):
572 Validateur operationnel
573 Verification d'absence de doublons dans la liste.
581 return _(tr(u": pas de présence de doublon dans la liste"))
583 def info_erreur_liste(self):
584 return _(tr(u"Les doublons ne sont pas permis"))
586 def default(self, valeur):
587 if valeur in self.liste:
588 raise ValError(ufmt(_tr((u"%s est un doublon")), valeur))
591 def convert(self, valeur):
598 def verif_item(self, valeur):
601 def verif(self, valeur):
602 if is_sequence(valeur):
605 if liste.count(val) != 1:
611 def get_into(self, liste_courante=None, into_courant=None):
613 Methode get_into spécifique pour validateur NoRepeat, on retourne
614 une liste de choix qui ne contient aucune valeur de into_courant
615 déjà contenue dans liste_courante
617 if into_courant is None:
621 for e in into_courant:
624 if liste_courante is not None and e in liste_courante:
626 liste_choix.append(e)
630 class LongStr(ListVal):
633 Validateur operationnel
634 Verification de la longueur d une chaine
637 def __init__(self, low, high):
638 ListVal.__init__(self, low=low, high=high)
644 return ufmt(_(u"longueur de la chaine entre %s et %s"), self.low, self.high)
646 def info_erreur_item(self):
647 return _(u"Longueur de la chaine incorrecte")
649 def convert(self, valeur):
654 def verif_item(self, valeur):
661 def default(self, valeur, low, high):
662 if not is_str(valeur):
663 raise ValError(ufmt(_tr((u"%s n'est pas une chaine")), repr(valeur)))
664 if valeur[0] == "'" and valeur[-1] == "'":
667 if len(valeur) < low or len(valeur) > high:
669 ufmt(_(tr(u"%s n'est pas de la bonne longueur")), repr(valeur)))
673 class OnlyStr(ListVal):
676 Validateur operationnel
677 Valide que c'est une chaine
681 ListVal.__init__(self)
685 return _(u"regarde si c'est une chaine")
687 def info_erreur_item(self):
688 return _(u"Ce n'est pas une chaine")
690 def convert(self, valeur):
695 def verif_item(self, valeur):
702 def default(self, valeur):
703 if not is_str(valeur):
704 raise ValError(ufmt(_tr((u"%s n'est pas une chaine")), repr(valeur)))
708 class OrdList(ListVal):
711 Validateur operationnel
712 Verification qu'une liste est croissante ou decroissante
715 def __init__(self, ord):
716 ListVal.__init__(self, ord=ord)
721 return ufmt(_(u"liste %s"), self.ord)
723 def info_erreur_liste(self):
724 return ufmt(_(u"La liste doit etre en ordre %s"), self.ord)
726 def convert(self, valeur):
733 def default(self, valeur, ord):
734 if self.ord == 'croissant':
735 if self.val is not None and valeur < self.val:
737 ufmt(_tr((u"%s n'est pas par valeurs croissantes")), repr(self.liste)))
738 elif self.ord == 'decroissant':
739 if self.val is not None and valeur > self.val:
741 ufmt(_tr((u"%s n'est pas par valeurs decroissantes")), repr(self.liste)))
745 def verif_item(self, valeur):
748 def get_into(self, liste_courante=None, into_courant=None):
750 Methode get_into spécifique pour validateur OrdList, on retourne
751 une liste de choix qui ne contient aucune valeur de into_courant
752 dont la valeur est inférieure à la dernière valeur de
753 liste_courante, si elle est différente de None.
755 if into_courant is None:
757 elif not liste_courante:
761 last_val = liste_choix[-1]
762 for e in into_courant:
763 if self.ord == 'croissant' and e <= last_val:
765 if self.ord == 'decroissant' and e >= last_val:
767 liste_choix.append(e)
774 Validateur operationnel
775 Cette classe est un validateur qui controle une liste de validateurs
776 Elle verifie qu'au moins un des validateurs de la liste valide la valeur
779 def __init__(self, validators=()):
780 if not is_sequence(validators):
781 validators = (validators,)
783 for validator in validators:
784 if type(validator) == types.FunctionType:
785 self.validators.append(FunctionVal(validator))
787 self.validators.append(validator)
791 return "\n ou ".join([v.info() for v in self.validators])
793 def convert(self, valeur):
794 for validator in self.validators:
796 return validator.convert(valeur)
799 raise ValError(ufmt(_tr((u"%s n'est pas du bon type")), repr(valeur)))
801 def info_erreur_item(self):
803 for v in self.validators:
804 err = v.info_erreur_item()
807 chaine = " \n ou ".join(l)
810 def info_erreur_liste(self):
812 for v in self.validators:
813 err = v.info_erreur_liste()
816 chaine = " \n ou ".join(l)
821 Si plusieurs validateurs sont reliés par un OU
822 il suffit qu'un seul des validateurs attende une liste
823 pour qu'on considère que leur union attend une liste.
825 for validator in self.validators:
826 v = validator.is_list()
831 def verif(self, valeur):
832 for validator in self.validators:
833 v = validator.verif(valeur)
838 def verif_item(self, valeur):
839 for validator in self.validators:
840 v = validator.verif_item(valeur)
845 def verif_cata(self):
847 for validator in self.validators:
848 v = validator.verif_cata()
850 infos.append(validator.cata_info)
852 self.cata_info = "\n".join(infos)
859 Dans le cas ou plusieurs validateurs sont reliés par un OU
860 il faut que tous les validateurs proposent un choix pour
861 qu'on considère que leur union propose un choix.
862 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
863 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
865 for validator in self.validators:
866 v = validator.has_into()
871 def get_into(self, liste_courante=None, into_courant=None):
873 Dans le cas ou plusieurs validateurs sont reliés par un OU
874 tous les validateurs doivent proposer un choix pour
875 qu'on considère que leur union propose un choix. Tous les choix
876 proposés par les validateurs sont réunis (opérateur d'union).
877 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
878 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
882 for validator in self.validators:
883 v_into = validator.get_into(liste_courante, into_courant)
886 validator_into.extend(v_into)
887 return validator_into
889 def valide_liste_partielle(self, liste_courante=None):
891 Méthode de validation de liste partielle pour le validateur Or.
892 Si un des validateurs gérés par le validateur Or considère la
893 liste comme valide, le validateur Or la considère comme valide.
895 for validator in self.validators:
896 v = validator.valide_liste_partielle(liste_courante)
905 Validateur operationnel
906 Cette classe est un validateur qui controle une liste de validateurs
907 Elle verifie que tous les validateurs de la liste valident la valeur
910 def __init__(self, validators=()):
911 if not is_sequence(validators):
912 validators = (validators,)
914 for validator in validators:
915 if type(validator) == types.FunctionType:
916 self.validators.append(FunctionVal(validator))
918 self.validators.append(validator)
919 if hasattr(validator, 'fonctions'):
920 for fonction in validator.fonctions:
921 f = getattr(validator, fonction)
922 setattr(self, fonction, f)
926 return "\n et ".join([v.info() for v in self.validators])
928 def convert(self, valeur):
929 for validator in self.validators:
930 valeur = validator.convert(valeur)
933 def info_erreur_item(self):
936 for v in self.validators:
937 if v.info_erreur_item() != " ":
939 chaine = v.info_erreur_item()
942 chaine = chaine + " \n et " + v.info_erreur_item()
945 def info_erreur_liste(self):
947 for v in self.validators:
948 if v.info_erreur_liste() != " ":
950 chaine = v.info_erreur_liste()
953 chaine = chaine + " \n et " + v.info_erreur_liste()
956 def verif(self, valeur):
957 for validator in self.validators:
958 v = validator.verif(valeur)
960 self.local_info = validator.info()
964 def verif_item(self, valeur):
965 for validator in self.validators:
966 v = validator.verif_item(valeur)
968 # L'info n'est probablement pas la meme que pour verif ???
969 self.local_info = validator.info()
973 def verif_cata(self):
975 for validator in self.validators:
976 v = validator.verif_cata()
978 infos.append(validator.cata_info)
980 self.cata_info = "\n".join(infos)
985 def valide_liste_partielle(self, liste_courante=None):
987 Méthode de validation de liste partielle pour le validateur And.
988 Tous les validateurs gérés par le validateur And doivent considérer
989 la liste comme valide, pour que le validateur And la considère
992 for validator in self.validators:
993 v = validator.valide_liste_partielle(liste_courante)
1000 Si plusieurs validateurs sont reliés par un ET
1001 il faut que tous les validateurs attendent une liste
1002 pour qu'on considère que leur intersection attende une liste.
1003 Exemple Range(2,5) ET Card(1) n'attend pas une liste
1004 Range(2,5) ET Pair attend une liste
1006 for validator in self.validators:
1007 v = validator.is_list()
1014 Dans le cas ou plusieurs validateurs sont reliés par un ET
1015 il suffit qu'un seul validateur propose un choix pour
1016 qu'on considère que leur intersection propose un choix.
1017 Exemple : Enum(1,2,3) ET entier pair, propose un choix
1018 En revanche, entier pair ET superieur à 10 ne propose pas de choix
1020 for validator in self.validators:
1021 v = validator.has_into()
1026 def get_into(self, liste_courante=None, into_courant=None):
1028 Dans le cas ou plusieurs validateurs sont reliés par un ET
1029 il suffit qu'un seul validateur propose un choix pour
1030 qu'on considère que leur intersection propose un choix. Tous les
1031 choix proposés par les validateurs sont croisés (opérateur
1033 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
1034 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
1036 for validator in self.validators:
1037 into_courant = validator.get_into(liste_courante, into_courant)
1038 if into_courant in ([], None):
1043 def do_liste(validators):
1045 Convertit une arborescence de validateurs en OrVal ou AndVal
1046 validators est une liste de validateurs ou de listes ou de tuples
1049 for validator in validators:
1050 if type(validator) == types.FunctionType:
1051 valids.append(FunctionVal(validator))
1052 elif type(validator) is tuple:
1053 valids.append(OrVal(do_liste(validator)))
1054 elif type(validator) is list:
1055 valids.append(AndVal(do_liste(validator)))
1057 valids.append(validator)
1061 def validatorFactory(validator):
1062 if type(validator) == types.FunctionType:
1063 return FunctionVal(validator)
1064 elif type(validator) is tuple:
1065 return OrVal(do_liste(validator))
1066 elif type(validator) is list:
1067 return AndVal(do_liste(validator))
1071 # Ci-dessous : exemples de validateur (peu testés)
1074 class RangeVal(ListVal):
1077 Exemple de classe validateur : verification qu'une valeur
1078 est dans un intervalle.
1079 Pour une liste on verifie que tous les elements sont
1081 Susceptible de remplacer les attributs "vale_min" "vale_max"
1085 def __init__(self, low, high):
1088 self.cata_info = ufmt(_(tr(u"%s doit être inférieur a %s")), low, high)
1091 return ufmt(_(tr(u"valeur dans l'intervalle %s , %s")), self.low, self.high)
1093 def convert_item(self, valeur):
1094 if valeur > self.low and valeur < self.high:
1096 raise ValError(ufmt(_(tr(u"%s devrait être comprise entre %s et %s")),
1097 valeur, self.low, self.high))
1099 def verif_item(self, valeur):
1100 return valeur > self.low and valeur < self.high
1102 def info_erreur_item(self):
1103 return ufmt(_(tr(u"La valeur doit etre comprise entre %s et %s")), self.low, self.high)
1105 def verif_cata(self):
1106 if self.low > self.high:
1111 class CardVal(Valid):
1114 Exemple de classe validateur : verification qu'une liste est
1115 d'une longueur superieur a un minimum (min) et inferieure
1117 Susceptible de remplacer les attributs "min" "max" dans les
1121 def __init__(self, min='**', max='**'):
1124 self.cata_info = ufmt(_(tr(u"%s doit etre inferieur a %s")), min, max)
1127 return ufmt(_(tr(u"longueur de liste comprise entre %s et %s")), self.min, self.max)
1129 def info_erreur_liste(self):
1131 _(tr(u"Le cardinal de la liste doit etre compris entre %s et %s")),
1135 return self.max == '**' or self.max > 1
1137 def get_into(self, liste_courante=None, into_courant=None):
1138 if into_courant is None:
1140 elif liste_courante is None:
1142 elif self.max == '**':
1144 elif len(liste_courante) < self.max:
1149 def convert(self, valeur):
1150 if is_sequence(valeur):
1152 elif valeur is None:
1156 if self.max != '**' and l > self.max:
1158 ufmt(_(tr(u"%s devrait etre de longueur inferieure a %s")), valeur, self.max))
1159 if self.min != '**' and l < self.min:
1161 ufmt(_(tr(u"%s devrait etre de longueur superieure a %s")), valeur, self.min))
1164 def verif_item(self, valeur):
1167 def verif(self, valeur):
1168 if is_sequence(valeur):
1169 if self.max != '**' and len(valeur) > self.max:
1171 if self.min != '**' and len(valeur) < self.min:
1175 if self.max != '**' and 1 > self.max:
1177 if self.min != '**' and 1 < self.min:
1181 def verif_cata(self):
1182 if self.min != '**' and self.max != '**' and self.min > self.max:
1186 def valide_liste_partielle(self, liste_courante=None):
1188 if liste_courante != None:
1189 if len(liste_courante) > self.max:
1194 class PairVal(ListVal):
1197 Exemple de classe validateur : verification qu'une valeur
1199 Pour une liste on verifie que tous les elements sont
1204 ListVal.__init__(self)
1208 return _(u"valeur paire")
1210 def info_erreur_item(self):
1211 return _(tr(u"La valeur saisie doit etre paire"))
1213 def convert(self, valeur):
1218 ufmt(_(tr(u"%s contient des valeurs non paires")), repr(valeur)))
1221 def default(self, valeur):
1224 def verif_item(self, valeur):
1225 if type(valeur) not in (int, long):
1227 return valeur % 2 == 0
1229 def verif(self, valeur):
1230 if is_sequence(valeur):
1241 class EnumVal(ListVal):
1244 Exemple de classe validateur : verification qu'une valeur
1245 est prise dans une liste de valeurs.
1246 Susceptible de remplacer l attribut "into" dans les catalogues
1249 def __init__(self, into=()):
1250 if not is_sequence(into):
1256 return "valeur dans %s" % `self.into`
1258 def convert_item(self, valeur):
1259 if valeur in self.into:
1262 ufmt(_(tr(u"%s contient des valeurs hors des choix possibles: %s ")),
1265 def verif_item(self, valeur):
1266 if valeur not in self.into:
1273 def get_into(self, liste_courante=None, into_courant=None):
1274 if into_courant is None:
1275 liste_choix = list(self.into)
1278 for e in into_courant:
1280 liste_choix.append(e)
1283 def info_erreur_item(self):
1284 return _(tr(u"La valeur n'est pas dans la liste des choix possibles"))
1287 def ImpairVal(valeur):
1289 Exemple de validateur
1290 Cette fonction est un validateur. Elle verifie que la valeur passee
1291 est bien un nombre impair.
1293 if is_sequence(valeur):
1303 ImpairVal.info = tr("valeur impaire")
1309 Exemple de validateur
1310 Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1311 que la somme des cles A et B vaut une valeur donnee
1312 en parametre du validateur
1315 def __init__(self, somme=10):
1320 return ufmt(_(u"valeur %s pour la somme des cles A et B "), self.somme)
1322 def verif(self, valeur):
1323 if is_sequence(valeur):
1325 if not val.has_key("A"):
1327 if not val.has_key("B"):
1329 if val["A"] + val["B"] != self.somme:
1333 if not valeur.has_key("A"):
1335 if not valeur.has_key("B"):
1337 if valeur["A"] + valeur["B"] != self.somme:
1342 class FunctionVal(Valid):
1345 Exemple de validateur
1346 Cette classe est un validateur qui est initialise avec une fonction
1349 def __init__(self, function):
1350 self.function = function
1353 return self.function.info
1355 def verif(self, valeur):
1356 return self.function(valeur)
1358 # MC ca ne devrait plus servir !
1359 CoercableFuncs = {types.IntType: int,
1360 types.LongType: long,
1361 types.FloatType: float,
1362 types.ComplexType: complex,
1363 types.UnicodeType: unicode}
1366 class TypeVal(ListVal):
1369 Exemple de validateur
1370 Cette classe est un validateur qui controle qu'une valeur
1371 est bien du type Python attendu.
1372 Pour une liste on verifie que tous les elements sont du bon type.
1373 Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1374 alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1377 def __init__(self, aType):
1378 # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1379 # type(1) == int;type(0.2)==float;etc.
1380 if type(aType) != types.TypeType:
1384 self.coerce = CoercableFuncs[aType]
1386 self.coerce = self.identity
1389 return ufmt(_(u"valeur de %s"), self.aType)
1391 def identity(self, value):
1392 if type(value) == self.aType:
1396 def convert_item(self, valeur):
1397 return self.coerce(valeur)
1399 def verif_item(self, valeur):
1407 class InstanceVal(ListVal):
1410 Exemple de validateur
1411 Cette classe est un validateur qui controle qu'une valeur est
1412 bien une instance (au sens Python) d'une classe
1413 Pour une liste on verifie chaque element de la liste
1416 def __init__(self, aClass):
1417 # Si aClass est une classe on la memorise dans self.aClass
1418 # sinon c'est une instance dont on memorise la classe
1419 if type(aClass) == types.InstanceType:
1420 # instance ancienne mode
1421 aClass = aClass.__class__
1422 elif type(aClass) == types.ClassType:
1423 # classe ancienne mode
1425 elif type(aClass) == type:
1426 # classe nouvelle mode
1428 elif isinstance(aClass, object):
1429 # instance nouvelle mode
1430 aClass = type(aClass)
1432 raise ValError(_(u"type non supporté"))
1434 self.aClass = aClass
1437 return ufmt(_(u"valeur d'instance de %s"), self.aClass.__name__)
1439 def verif_item(self, valeur):
1440 if not isinstance(valeur, self.aClass):
1445 class VerifTypeTuple(Valid, ListVal):
1447 def __init__(self, typeDesTuples):
1448 self.typeDesTuples = typeDesTuples
1449 Valid.__init__(self)
1453 return _(u"tuple de la forme :")+str(self.typeDesTuples)
1455 def info_erreur_liste(self):
1456 return _(u"Les types ne sont pas : ") +str(self.typeDesTuples)
1458 def default(self, valeur):
1464 def convert_item(self, valeur):
1465 if len(valeur) != len(self.typeDesTuples):
1467 ufmt(_(u"%s devrait etre de type %s "), valeur, self.typeDesTuples))
1468 for i in range(len(valeur)):
1469 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1472 ufmt(_(u"%s devrait etre de type %s "), valeur, self.typeDesTuples))
1475 def verif_item(self, valeur):
1477 if len(valeur) != len(self.typeDesTuples):
1479 for i in range(len(valeur)):
1480 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1487 def verifType(self, valeur, type_permis):
1488 if type_permis == 'R':
1489 if type(valeur) in (types.IntType, types.FloatType, types.LongType):
1491 elif type_permis == 'I':
1492 if type(valeur) in (types.IntType, types.LongType):
1494 elif type_permis == 'C':
1495 if self.is_complexe(valeur):
1497 elif type_permis == 'TXM':
1498 if type(valeur) == types.StringType:
1502 def verif(self, valeur):
1503 if type(valeur) in (types.ListType, types.TupleType):
1504 liste = list(valeur)
1506 if self.verif_item(val) != 1:
1511 class VerifExiste(ListVal):
1514 fonctionne avec into
1515 Met une liste à jour selon les mot clefs existant
1516 exemple si into = ("A","B","C")
1517 si au niveau N du JDC les objets "A" et "C" existe
1518 alors la liste des into deviendra ( "A","C")
1520 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1521 niveauVerif est defini par rapport au Noeud :
1522 exemple niveauVerif = 1 : on verifie les freres
1523 niveauVerif = 2 : on verifie les oncles..
1526 def __init__(self, niveauVerif):
1527 ListVal.__init__(self)
1528 self.niveauVerif = niveauVerif
1530 self.listeDesFreres = ()
1531 self.fonctions = ('verifie_liste', 'set_MCSimp')
1536 def verifie_liste(self, liste):
1537 self.set_MCSimp(self.MCSimp)
1539 if not(item in self.listeDesFreres):
1543 def verif_item(self, valeur):
1544 self.set_MCSimp(self.MCSimp)
1545 if valeur in self.listeDesFreres:
1549 def set_MCSimp(self, MCSimp):
1550 self.MCSimp = MCSimp
1551 k = self.niveauVerif
1557 # on met la liste à jour
1558 parent.forceRecalcul = self.niveauVerif
1559 self.listeDesFreres = parent.liste_mc_presents()
1561 def convert_item(self, valeur):
1562 if valeur in self.listeDesFreres:
1565 ufmt(_(u"%s n'est pas dans %s"), valeur, self.listeDesFreres))
1568 class RegExpVal(ListVal):
1571 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1574 errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1576 def __init__(self, pattern):
1577 self.pattern = pattern
1578 self.compiled_regexp = re.compile(pattern)
1581 return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
1583 def verif_item(self, valeur):
1584 if self.compiled_regexp.match(valeur):
1587 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1589 def convert_item(self, valeur):
1590 if self.compiled_regexp.match(valeur):
1593 raise ValError(self.errormsg %
1594 {"value": valeur, "pattern": self.pattern})
1597 class FileExtVal(RegExpVal):
1600 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1603 def __init__(self, ext):
1605 self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1607 RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
1610 return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext