2 # Copyright (C) 2007-2015 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 # ======================================================================
24 Ce module contient toutes les classes necessaires pour
25 implanter le concept de validateur dans Accas
30 from N_ASSD import ASSD
31 from N_types import is_int, is_float_or_int, is_complex, is_number, is_str, is_sequence
32 from strfunc import convert, ufmt
33 from Extensions.i18n import tr
37 class ValError(Exception):
42 if hasattr(cls, "__mro__"):
45 for base in cls.__bases__:
46 mro.extend(cls_mro(base))
52 def __init__(self, name):
57 def register(self, T, A):
61 # (a) verifier si l'objet peut s'adapter au protocole
62 adapt = getattr(obj, '__adapt__', None)
64 # on demande à l'objet obj de réaliser lui-meme l'adaptation
67 # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
69 for T in cls_mro(obj.__class__):
70 if T in self.registry:
71 return self.registry[T](obj, self, **self.args)
73 # (c) utiliser l'adapteur par defaut
74 return self.default(obj, **self.args)
76 def default(self, obj, **args):
77 raise TypeError("Can't adapt %s to %s" %
78 (obj.__class__.__name__, self.name))
81 class PProtocol(Protocol):
83 """Verificateur de protocole paramétré (classe de base)"""
84 # Protocole paramétré. Le registre est unique pour toutes les instances.
85 # La methode register est une methode de classe
88 def __init__(self, name, **args):
92 def register(cls, T, A):
94 register = classmethod(register)
97 class ListProtocol(Protocol):
99 """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
101 def default(self, obj):
102 if type(obj) is tuple:
103 if len(obj) > 0 and obj[0] in ('RI', 'MP'):
104 # il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
108 elif type(obj) is list:
111 # pas de valeur affecte. La cardinalite vaut 0
114 # il s'agit d'une chaine. La cardinalite vaut 1
118 # si l'objet supporte len, on a la cardinalite
125 listProto = ListProtocol("list")
128 class TypeProtocol(PProtocol):
130 """Verificateur de type parmi une liste de types possibles"""
131 # pas de registre par instance. Registre unique pour toutes les instances
135 def __init__(self, name, typ=None):
136 PProtocol.__init__(self, name, typ=typ)
139 def default(self, obj, typ):
142 for type_permis in typ:
143 if type_permis == 'R':
144 if is_float_or_int(obj):
146 elif type_permis == 'I':
149 elif type_permis == 'C':
150 if self.is_complexe(obj):
152 elif type_permis == 'TXM':
155 elif type_permis == 'shell':
158 elif type_permis == 'Fichier':
160 if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj):
164 ufmt(_(tr(u"%s n'est pas un fichier valide")), repr(obj)))
165 elif type_permis == 'FichierNoAbs':
167 if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")):
171 ufmt(_(tr("%s n'est pas un fichier valide")), repr(obj)))
172 elif type_permis == 'Repertoire':
174 if os.path.isdir(obj):
178 ufmt(_(tr(u"%s n'est pas un repertoire valide")), repr(obj)))
179 elif type(type_permis) == types.ClassType or isinstance(type_permis, type):
181 if self.is_object_from(obj, type_permis):
183 except Exception, err:
185 elif type(type_permis) == types.InstanceType or isinstance(type_permis, object):
187 if type_permis.__convert__(obj):
189 except Exception, err:
192 print convert(ufmt(_(tr(u"Type non encore gere %s")), `type_permis`))
194 ufmt(_(tr(u"%s (de type %s) n'est pas d'un type autorise: %s %s")),
195 repr(obj), type(obj), typ, unicode(err)))
197 def is_complexe(self, valeur):
198 """ Retourne 1 si valeur est un complexe, 0 sinon """
199 if is_number(valeur):
200 # Pour permettre l'utilisation de complexes Python (accepte les
203 elif type(valeur) != tuple:
204 # On n'autorise pas les listes pour les complexes
206 elif len(valeur) != 3:
209 # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
210 # valeur suivie de 2 reels.
211 if valeur[0].strip() in ('RI', 'MP'):
213 v1 = reelProto.adapt(valeur[1]), reelProto.adapt(valeur[2])
220 def is_object_from(self, objet, classe):
222 Retourne 1 si objet est une instance de la classe classe, 0 sinon
224 convert = getattr(classe, '__convert__', None)
225 if convert is not None:
226 # classe verifie les valeurs
230 except ValueError, err:
234 # On accepte les instances de la classe et des classes derivees
235 return isinstance(objet, classe)
237 reelProto = TypeProtocol("reel", typ=('R',))
240 class CardProtocol(PProtocol):
242 """Verificateur de cardinalité """
243 # pas de registre par instance. Registre unique pour toutes les instances
246 def __init__(self, name, min=1, max=1):
247 PProtocol.__init__(self, name, min=min, max=max)
249 def default(self, obj, min, max):
251 if length < min or length > max:
254 _(tr(u"Nombre d'arguments de %s incorrect (min = %s, max = %s)")),
255 repr(obj), min, max))
259 class IntoProtocol(PProtocol):
261 """Verificateur de choix possibles : liste discrète ou intervalle"""
262 # pas de registre par instance. Registre unique pour toutes les instances
265 def __init__(self, name, into=None, val_min='**', val_max='**'):
267 self, name, into=into, val_min=val_min, val_max=val_max)
268 self.val_min = val_min
269 self.val_max = val_max
271 def default(self, obj, into, val_min, val_max):
276 _(tr(u"La valeur : %s ne fait pas partie des choix possibles %s")),
279 # on est dans le cas d'un ensemble continu de valeurs possibles
281 if is_float_or_int(obj):
286 if obj < val_min or obj > val_max:
289 _(tr(u"La valeur : %s est en dehors du domaine de validite [ %s , %s ]")),
290 repr(obj), self.val_min, self.val_max))
295 # exemple de classe pour verificateur de type
296 # on utilise des instances de classe comme type (typ=MinStr(3,6), par
299 def __init__(self, min, max):
303 def __convert__(self, valeur):
304 if is_str(valeur) and self.min <= len(valeur) <= self.max:
308 _(tr(u"%s n'est pas une chaine de longueur comprise entre %s et %s")),
309 valeur, self.min, self.max))
312 return ufmt(_(tr(u"TXM de longueur entre %s et %s")), self.min, self.max)
315 class Valid(PProtocol):
318 Cette classe est la classe mere des validateurs Accas
319 Elle doit etre derivee
320 Elle presente la signature des methodes indispensables pour son bon
321 fonctionnement et dans certains cas leur comportement par défaut.
323 @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
324 @type cata_info: C{string}
328 def __init__(self, **args):
329 PProtocol.__init__(self, "valid", **args)
333 Cette methode retourne une chaine de caractères informative sur
334 la validation demandée par le validateur. Elle est utilisée
335 pour produire le compte-rendu de validité du mot clé associé.
337 return _(u"valeur valide")
341 Cette methode retourne une chaine de caractère qui permet
342 de construire un message d'aide en ligne.
343 En général, le message retourné est le meme que celui retourné par la
348 def info_erreur_item(self):
350 Cette méthode permet d'avoir un message d'erreur pour un item
351 dans une liste dans le cas ou le validateur fait des vérifications
352 sur les items d'une liste. Si le validateur fait seulement des
353 vérifications sur la liste elle meme et non sur ses items, la méthode
354 doit retourner une chaine vide.
358 def info_erreur_liste(self):
360 Cette méthode a un comportement complémentaire de celui de
361 info_erreur_item. Elle retourne un message d'erreur lié uniquement
362 aux vérifications sur la liste elle meme et pas sur ses items.
363 Dans le cas où le validateur ne fait pas de vérification sur des
364 listes, elle retourne une chaine vide
368 def verif(self, valeur):
370 Cette methode sert a verifier si la valeur passee en argument est consideree
371 comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
372 (valide) sinon 0 (invalide).
374 @type valeur: tout type python
375 @param valeur: valeur du mot cle a valider
377 @return: indicateur de validite 1 (valide) ou 0 (invalide)
379 raise NotImplementedError("Must be implemented")
381 def verif_item(self, valeur):
383 La methode verif du validateur effectue une validation complete de
384 la valeur. valeur peut etre un scalaire ou une liste. Le validateur
385 doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
386 methode is_list doit retourner 1).
387 La methode valid_item sert pour effectuer des validations partielles
388 de liste. Elle doit uniquement verifier la validite d'un item de
389 liste mais pas les caracteristiques de la liste.
393 def valide_liste_partielle(self, liste_courante):
395 Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
396 ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
397 veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
399 En général un validateur effectue la meme validation pour les listes partielles et les
402 return self.verif(liste_courante)
404 def verif_cata(self):
406 Cette methode sert a realiser des verifications du validateur lui meme.
407 Elle est facultative et retourne 1 (valide) par defaut.
408 Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
409 parametres de definition ne sont pas corrects.
410 La raison de l'invalidite est stockee dans l'attribut cata_info.
413 @return: indicateur de validite 1 (valide) ou 0 (invalide)
419 Cette méthode retourne un entier qui indique si le validateur
420 permet les listes (valeur 1) ou ne les permet pas (valeur 0).
421 Par défaut, un validateur n'autorise que des scalaires.
427 Cette méthode retourne un entier qui indique si le validateur
428 propose une liste de choix (valeur 1) ou n'en propose pas.
429 Par défaut, un validateur n'en propose pas.
433 def get_into(self, liste_courante=None, into_courant=None):
435 Cette méthode retourne la liste de choix proposée par le validateur.
436 Si le validateur ne propose pas de liste de choix, la méthode
438 L'argument d'entrée liste_courante, s'il est différent de None, donne
439 la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
440 méthode get_into doit calculer la liste des choix en en tenant
441 compte. Par exemple, si le validateur n'autorise pas les répétitions,
442 la liste des choix retournée ne doit pas contenir les choix déjà
443 contenus dans liste_courante.
444 L'argument d'entrée into_courant, s'il est différent de None, donne
445 la liste des choix proposés par d'autres validateurs. Dans ce cas,
446 la méthode get_into doit calculer la liste des choix à retourner
447 en se limitant à cette liste initiale. Par exemple, si into_courant
448 vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
449 la méthode ne doit retourner que (3,).
451 La méthode get_into peut retourner une liste vide [], ce qui veut
452 dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
453 peut etre normale : l''utilisateur a utilisé tous les choix, ou
454 résulter d'une incohérence des validateurs :
455 choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
456 faire la différence entre ces deux situations.
461 class ListVal(Valid):
464 Cette classe sert de classe mère pour tous les validateurs qui acceptent
471 def get_into(self, liste_courante=None, into_courant=None):
473 Cette méthode get_into effectue un traitement général qui consiste
474 a filtrer la liste de choix into_courant, si elle existe, en ne
475 conservant que les valeurs valides (appel de la méthode valid).
477 if into_courant is None:
481 for e in into_courant:
483 liste_choix.append(e)
486 def convert(self, valeur):
488 Méthode convert pour les validateurs de listes. Cette méthode
489 fait appel à la méthode convert_item sur chaque élément de la
492 if is_sequence(valeur):
494 self.convert_item(val)
497 return self.convert_item(valeur)
499 def verif(self, valeur):
501 Méthode verif pour les validateurs de listes. Cette méthode
502 fait appel à la méthode verif_item sur chaque élément de la
503 liste. Si valeur est un paramètre, on utilise sa valeur effective
506 if is_sequence(valeur):
508 if not self.verif_item(val):
512 return self.verif_item(valeur)
515 class Compulsory(ListVal):
517 Validateur operationnel
518 Verification de la présence obligatoire d'un élément dans une liste
522 def __init__(self, elem=()):
523 if not is_sequence(elem):
525 Valid.__init__(self, elem=elem)
530 return ufmt(_(tr(u"valeur %s obligatoire")), `self.elem`)
532 def default(self, valeur, elem):
535 def verif_item(self, valeur):
538 def convert(self, valeur):
539 elem = list(self.elem)
546 ufmt(_(tr(u"%s ne contient pas les elements obligatoires : %s ")),
553 def verif(self, valeur):
554 if not is_sequence(valeur):
558 for val in self.elem:
563 def info_erreur_item(self):
564 return _(u"La valeur n'est pas dans la liste des choix possibles")
567 class Together(ListVal):
569 Validateur operationnel
570 si un des éléments est présent les autres doivent aussi l'être
574 def __init__(self, elem=()):
575 if not is_sequence(elem):
577 Valid.__init__(self, elem=elem)
582 return ufmt(_(tr(u"%s present ensemble")), `self.elem`)
584 def default(self, valeur, elem):
587 def verif_item(self, valeur):
590 def convert(self, valeur):
591 elem = list(self.elem)
594 if v in elem: elem.remove(v)
595 if ( len(elem) == 0 ): return valeur
596 if len(elem) != len(list(self.elem)) :
597 raise ValError( ufmt(_(tr(u"%s ne contient pas les elements devant etre presents ensemble: %s ")), valeur, elem))
603 def verif(self, valeur):
604 if not is_sequence(valeur):
609 for val in self.elem:
610 if val in liste: compte += 1
611 if ( compte == 0 ): return 1
612 if ( compte != len( list(self.elem) ) ): return 0
615 def info_erreur_item(self):
616 return _(u"La valeur n'est pas dans la liste des choix possibles")
619 class Absent(ListVal):
621 Validateur operationnel
622 si un des éléments est présent non valide
626 def __init__(self, elem=()):
627 if not is_sequence(elem):
629 Valid.__init__(self, elem=elem)
634 return ufmt(_(tr(u"%s absent")), `self.elem`)
636 def default(self, valeur, elem):
639 def verif_item(self, valeur):
642 def convert(self, valeur):
643 elem = list(self.elem)
647 raise ValError( ufmt(_(tr(u"%s n'est pas autorise : %s ")), v, elem))
653 def verif(self, valeur):
654 if not is_sequence(valeur):
658 for val in self.elem:
659 if val in liste: return 0
662 def info_erreur_item(self):
663 return _(u"La valeur n'est pas dans la liste des choix possibles")
666 class NoRepeat(ListVal):
668 Validateur operationnel
669 Verification d'absence de doublons dans la liste.
676 return _(u": pas de présence de doublon dans la liste")
678 def info_erreur_liste(self):
679 return _(u"Les doublons ne sont pas permis")
681 def default(self, valeur):
682 if valeur in self.liste:
683 raise ValError(ufmt(_(tr(u"%s est un doublon")), valeur))
686 def convert(self, valeur):
693 def verif_item(self, valeur):
696 def verif(self, valeur):
697 if is_sequence(valeur):
700 if liste.count(val) != 1:
706 def get_into(self, liste_courante=None, into_courant=None):
708 Methode get_into spécifique pour validateur NoRepeat, on retourne
709 une liste de choix qui ne contient aucune valeur de into_courant
710 déjà contenue dans liste_courante
712 if into_courant is None:
716 for e in into_courant:
719 if liste_courante is not None and e in liste_courante:
721 liste_choix.append(e)
725 class LongStr(ListVal):
728 Validateur operationnel
729 Verification de la longueur d une chaine
732 def __init__(self, low, high):
733 ListVal.__init__(self, low=low, high=high)
739 return ufmt(_(tr(u"longueur de la chaine entre %s et %s")), self.low, self.high)
741 def info_erreur_item(self):
742 return _(tr(u"Longueur de la chaine incorrecte"))
744 def convert(self, valeur):
749 def verif_item(self, valeur):
756 def default(self, valeur, low, high):
757 if not is_str(valeur):
758 raise ValError(ufmt(_(tr(u"%s n'est pas une chaine")), repr(valeur)))
759 if valeur[0] == "'" and valeur[-1] == "'":
762 if len(valeur) < low or len(valeur) > high:
764 ufmt(_(tr(u"%s n'est pas de la bonne longueur")), repr(valeur)))
768 class OnlyStr(ListVal):
771 Validateur operationnel
772 Valide que c'est une chaine
776 ListVal.__init__(self)
780 return _(u"regarde si c'est une chaine")
782 def info_erreur_item(self):
783 return _(u"Ce n'est pas une chaine")
785 def convert(self, valeur):
790 def verif_item(self, valeur):
797 def default(self, valeur):
798 if not is_str(valeur):
799 raise ValError(ufmt(_(tr(u"%s n'est pas une chaine")), repr(valeur)))
803 class OrdList(ListVal):
806 Validateur operationnel
807 Verification qu'une liste est croissante ou decroissante
810 def __init__(self, ord):
811 ListVal.__init__(self, ord=ord)
816 return ufmt(_(tr(u"liste %s")), self.ord)
818 def info_erreur_liste(self):
819 return ufmt(_(tr(u"La liste doit etre en ordre %s")), self.ord)
821 def convert(self, valeur):
828 def default(self, valeur, ord):
829 if self.ord == 'croissant':
830 if self.val is not None and valeur < self.val:
832 ufmt(_(tr(u"%s n'est pas par valeurs croissantes")), repr(self.liste)))
833 elif self.ord == 'decroissant':
834 if self.val is not None and valeur > self.val:
836 ufmt(_(tr(u"%s n'est pas par valeurs decroissantes")), repr(self.liste)))
840 def verif_item(self, valeur):
843 def get_into(self, liste_courante=None, into_courant=None):
845 Methode get_into spécifique pour validateur OrdList, on retourne
846 une liste de choix qui ne contient aucune valeur de into_courant
847 dont la valeur est inférieure à la dernière valeur de
848 liste_courante, si elle est différente de None.
850 if into_courant is None:
852 elif not liste_courante:
856 last_val = liste_choix[-1]
857 for e in into_courant:
858 if self.ord == 'croissant' and e <= last_val:
860 if self.ord == 'decroissant' and e >= last_val:
862 liste_choix.append(e)
869 Validateur operationnel
870 Cette classe est un validateur qui controle une liste de validateurs
871 Elle verifie qu'au moins un des validateurs de la liste valide la valeur
874 def __init__(self, validators=()):
875 if not is_sequence(validators):
876 validators = (validators,)
878 for validator in validators:
879 if type(validator) == types.FunctionType:
880 self.validators.append(FunctionVal(validator))
882 self.validators.append(validator)
886 return "\n ou ".join([v.info() for v in self.validators])
888 def convert(self, valeur):
889 for validator in self.validators:
891 return validator.convert(valeur)
894 raise ValError(ufmt(_(tr(u"%s n'est pas du bon type")), repr(valeur)))
896 def info_erreur_item(self):
898 for v in self.validators:
899 err = v.info_erreur_item()
902 chaine = " \n ou ".join(l)
905 def info_erreur_liste(self):
907 for v in self.validators:
908 err = v.info_erreur_liste()
911 chaine = " \n ou ".join(l)
916 Si plusieurs validateurs sont reliés par un OU
917 il suffit qu'un seul des validateurs attende une liste
918 pour qu'on considère que leur union attend une liste.
920 for validator in self.validators:
921 v = validator.is_list()
926 def verif(self, valeur):
927 for validator in self.validators:
928 v = validator.verif(valeur)
933 def verif_item(self, valeur):
934 for validator in self.validators:
935 v = validator.verif_item(valeur)
940 def verif_cata(self):
942 for validator in self.validators:
943 v = validator.verif_cata()
945 infos.append(validator.cata_info)
947 self.cata_info = "\n".join(infos)
954 Dans le cas ou plusieurs validateurs sont reliés par un OU
955 il faut que tous les validateurs proposent un choix pour
956 qu'on considère que leur union propose un choix.
957 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
958 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
960 for validator in self.validators:
961 v = validator.has_into()
966 def get_into(self, liste_courante=None, into_courant=None):
968 Dans le cas ou plusieurs validateurs sont reliés par un OU
969 tous les validateurs doivent proposer un choix pour
970 qu'on considère que leur union propose un choix. Tous les choix
971 proposés par les validateurs sont réunis (opérateur d'union).
972 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
973 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
977 for validator in self.validators:
978 v_into = validator.get_into(liste_courante, into_courant)
981 validator_into.extend(v_into)
982 return validator_into
984 def valide_liste_partielle(self, liste_courante=None):
986 Méthode de validation de liste partielle pour le validateur Or.
987 Si un des validateurs gérés par le validateur Or considère la
988 liste comme valide, le validateur Or la considère comme valide.
990 for validator in self.validators:
991 v = validator.valide_liste_partielle(liste_courante)
1000 Validateur operationnel
1001 Cette classe est un validateur qui controle une liste de validateurs
1002 Elle verifie que tous les validateurs de la liste valident la valeur
1005 def __init__(self, validators=()):
1006 if not is_sequence(validators):
1007 validators = (validators,)
1008 self.validators = []
1009 for validator in validators:
1010 if type(validator) == types.FunctionType:
1011 self.validators.append(FunctionVal(validator))
1013 self.validators.append(validator)
1014 if hasattr(validator, 'fonctions'):
1015 for fonction in validator.fonctions:
1016 f = getattr(validator, fonction)
1017 setattr(self, fonction, f)
1021 return "\n et ".join([v.info() for v in self.validators])
1023 def convert(self, valeur):
1024 for validator in self.validators:
1025 valeur = validator.convert(valeur)
1028 def info_erreur_item(self):
1031 for v in self.validators:
1032 if v.info_erreur_item() != " ":
1034 chaine = v.info_erreur_item()
1037 chaine = chaine + " \n et " + v.info_erreur_item()
1040 def info_erreur_liste(self):
1042 for v in self.validators:
1043 if v.info_erreur_liste() != " ":
1045 chaine = v.info_erreur_liste()
1048 chaine = chaine + " \n et " + v.info_erreur_liste()
1051 def verif(self, valeur):
1052 for validator in self.validators:
1053 v = validator.verif(valeur)
1055 self.local_info = validator.info()
1059 def verif_item(self, valeur):
1060 for validator in self.validators:
1061 v = validator.verif_item(valeur)
1063 # L'info n'est probablement pas la meme que pour verif ???
1064 self.local_info = validator.info()
1068 def verif_cata(self):
1070 for validator in self.validators:
1071 v = validator.verif_cata()
1073 infos.append(validator.cata_info)
1075 self.cata_info = "\n".join(infos)
1080 def valide_liste_partielle(self, liste_courante=None):
1082 Méthode de validation de liste partielle pour le validateur And.
1083 Tous les validateurs gérés par le validateur And doivent considérer
1084 la liste comme valide, pour que le validateur And la considère
1087 for validator in self.validators:
1088 v = validator.valide_liste_partielle(liste_courante)
1095 Si plusieurs validateurs sont reliés par un ET
1096 il faut que tous les validateurs attendent une liste
1097 pour qu'on considère que leur intersection attende une liste.
1098 Exemple Range(2,5) ET Card(1) n'attend pas une liste
1099 Range(2,5) ET Pair attend une liste
1101 for validator in self.validators:
1102 v = validator.is_list()
1109 Dans le cas ou plusieurs validateurs sont reliés par un ET
1110 il suffit qu'un seul validateur propose un choix pour
1111 qu'on considère que leur intersection propose un choix.
1112 Exemple : Enum(1,2,3) ET entier pair, propose un choix
1113 En revanche, entier pair ET superieur à 10 ne propose pas de choix
1115 for validator in self.validators:
1116 v = validator.has_into()
1121 def get_into(self, liste_courante=None, into_courant=None):
1123 Dans le cas ou plusieurs validateurs sont reliés par un ET
1124 il suffit qu'un seul validateur propose un choix pour
1125 qu'on considère que leur intersection propose un choix. Tous les
1126 choix proposés par les validateurs sont croisés (opérateur
1128 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
1129 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
1131 for validator in self.validators:
1132 into_courant = validator.get_into(liste_courante, into_courant)
1133 if into_courant in ([], None):
1138 def do_liste(validators):
1140 Convertit une arborescence de validateurs en OrVal ou AndVal
1141 validators est une liste de validateurs ou de listes ou de tuples
1144 for validator in validators:
1145 if type(validator) == types.FunctionType:
1146 valids.append(FunctionVal(validator))
1147 elif type(validator) is tuple:
1148 valids.append(OrVal(do_liste(validator)))
1149 elif type(validator) is list:
1150 valids.append(AndVal(do_liste(validator)))
1152 valids.append(validator)
1156 def validatorFactory(validator):
1157 if type(validator) == types.FunctionType:
1158 return FunctionVal(validator)
1159 elif type(validator) is tuple:
1160 return OrVal(do_liste(validator))
1161 elif type(validator) is list:
1162 return AndVal(do_liste(validator))
1166 # Ci-dessous : exemples de validateur (peu testés)
1169 class RangeVal(ListVal):
1172 Exemple de classe validateur : verification qu'une valeur
1173 est dans un intervalle.
1174 Pour une liste on verifie que tous les elements sont
1176 Susceptible de remplacer les attributs "vale_min" "vale_max"
1180 def __init__(self, low, high):
1183 self.cata_info = ufmt(_(tr(u"%s doit etre inferieur a %s")), low, high)
1186 return ufmt(_(tr(u"valeur dans l'intervalle %s , %s")), self.low, self.high)
1188 def convert_item(self, valeur):
1189 if valeur > self.low and valeur < self.high:
1191 raise ValError(ufmt(_(tr(u"%s devrait etre comprise entre %s et %s")),
1192 valeur, self.low, self.high))
1194 def verif_item(self, valeur):
1195 return valeur > self.low and valeur < self.high
1197 def info_erreur_item(self):
1198 return ufmt(_(tr(u"La valeur doit etre comprise entre %s et %s")), self.low, self.high)
1200 def verif_cata(self):
1201 if self.low > self.high:
1206 class CardVal(Valid):
1209 Exemple de classe validateur : verification qu'une liste est
1210 d'une longueur superieur a un minimum (min) et inferieure
1212 Susceptible de remplacer les attributs "min" "max" dans les
1216 def __init__(self, min='**', max='**'):
1219 self.cata_info = ufmt(_(tr(u"%s doit etre inferieur a %s")), min, max)
1222 return ufmt(_(tr(u"longueur de liste comprise entre %s et %s")), self.min, self.max)
1224 def info_erreur_liste(self):
1226 _(tr(u"Le cardinal de la liste doit etre compris entre %s et %s")),
1230 return self.max == '**' or self.max > 1
1232 def get_into(self, liste_courante=None, into_courant=None):
1233 if into_courant is None:
1235 elif liste_courante is None:
1237 elif self.max == '**':
1239 elif len(liste_courante) < self.max:
1244 def convert(self, valeur):
1245 if is_sequence(valeur):
1247 elif valeur is None:
1251 if self.max != '**' and l > self.max:
1253 ufmt(_(tr(u"%s devrait etre de longueur inferieure a %s")), valeur, self.max))
1254 if self.min != '**' and l < self.min:
1256 ufmt(_(tr(u"%s devrait etre de longueur superieure a %s")), valeur, self.min))
1259 def verif_item(self, valeur):
1262 def verif(self, valeur):
1263 if is_sequence(valeur):
1264 if self.max != '**' and len(valeur) > self.max:
1266 if self.min != '**' and len(valeur) < self.min:
1270 if self.max != '**' and 1 > self.max:
1272 if self.min != '**' and 1 < self.min:
1276 def verif_cata(self):
1277 if self.min != '**' and self.max != '**' and self.min > self.max:
1281 def valide_liste_partielle(self, liste_courante=None):
1283 if liste_courante != None:
1284 if len(liste_courante) > self.max:
1289 class PairVal(ListVal):
1292 Exemple de classe validateur : verification qu'une valeur
1294 Pour une liste on verifie que tous les elements sont
1299 ListVal.__init__(self)
1303 return _(u"valeur paire")
1305 def info_erreur_item(self):
1306 return _(u"La valeur saisie doit etre paire")
1308 def convert(self, valeur):
1313 ufmt(_(tr(u"%s contient des valeurs non paires")), repr(valeur)))
1316 def default(self, valeur):
1319 def verif_item(self, valeur):
1320 if type(valeur) not in (int, long):
1322 return valeur % 2 == 0
1324 def verif(self, valeur):
1325 if is_sequence(valeur):
1336 class EnumVal(ListVal):
1339 Exemple de classe validateur : verification qu'une valeur
1340 est prise dans une liste de valeurs.
1341 Susceptible de remplacer l attribut "into" dans les catalogues
1344 def __init__(self, into=()):
1345 if not is_sequence(into):
1351 return "valeur dans %s" % `self.into`
1353 def convert_item(self, valeur):
1354 if valeur in self.into:
1357 ufmt(_(tr(u"%s contient des valeurs hors des choix possibles: %s ")),
1360 def verif_item(self, valeur):
1361 if valeur not in self.into:
1368 def get_into(self, liste_courante=None, into_courant=None):
1369 if into_courant is None:
1370 liste_choix = list(self.into)
1373 for e in into_courant:
1375 liste_choix.append(e)
1378 def info_erreur_item(self):
1379 return _(u"La valeur n'est pas dans la liste des choix possibles")
1382 def ImpairVal(valeur):
1384 Exemple de validateur
1385 Cette fonction est un validateur. Elle verifie que la valeur passee
1386 est bien un nombre impair.
1388 if is_sequence(valeur):
1398 ImpairVal.info = "valeur impaire"
1404 Exemple de validateur
1405 Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1406 que la somme des cles A et B vaut une valeur donnee
1407 en parametre du validateur
1410 def __init__(self, somme=10):
1415 return ufmt(_(tr(u"valeur %s pour la somme des cles A et B ")), self.somme)
1417 def verif(self, valeur):
1418 if is_sequence(valeur):
1420 if not val.has_key("A"):
1422 if not val.has_key("B"):
1424 if val["A"] + val["B"] != self.somme:
1428 if not valeur.has_key("A"):
1430 if not valeur.has_key("B"):
1432 if valeur["A"] + valeur["B"] != self.somme:
1437 class FunctionVal(Valid):
1440 Exemple de validateur
1441 Cette classe est un validateur qui est initialise avec une fonction
1444 def __init__(self, function):
1445 self.function = function
1448 return self.function.info
1450 def verif(self, valeur):
1451 return self.function(valeur)
1453 def verif_item(self, valeur):
1454 return self.function(valeur)
1456 def convert(self, valeur):
1459 # MC ca ne devrait plus servir !
1460 CoercableFuncs = {types.IntType: int,
1461 types.LongType: long,
1462 types.FloatType: float,
1463 types.ComplexType: complex,
1464 types.UnicodeType: unicode}
1467 class TypeVal(ListVal):
1470 Exemple de validateur
1471 Cette classe est un validateur qui controle qu'une valeur
1472 est bien du type Python attendu.
1473 Pour une liste on verifie que tous les elements sont du bon type.
1474 Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1475 alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1478 def __init__(self, aType):
1479 # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1480 # type(1) == int;type(0.2)==float;etc.
1481 if type(aType) != types.TypeType:
1485 self.coerce = CoercableFuncs[aType]
1487 self.coerce = self.identity
1490 return ufmt(_(tr(u"valeur de %s")), self.aType)
1492 def identity(self, value):
1493 if type(value) == self.aType:
1497 def convert_item(self, valeur):
1498 return self.coerce(valeur)
1500 def verif_item(self, valeur):
1508 class InstanceVal(ListVal):
1511 Exemple de validateur
1512 Cette classe est un validateur qui controle qu'une valeur est
1513 bien une instance (au sens Python) d'une classe
1514 Pour une liste on verifie chaque element de la liste
1517 def __init__(self, aClass):
1518 # Si aClass est une classe on la memorise dans self.aClass
1519 # sinon c'est une instance dont on memorise la classe
1520 if type(aClass) == types.InstanceType:
1521 # instance ancienne mode
1522 aClass = aClass.__class__
1523 elif type(aClass) == types.ClassType:
1524 # classe ancienne mode
1526 elif type(aClass) == type:
1527 # classe nouvelle mode
1529 elif isinstance(aClass, object):
1530 # instance nouvelle mode
1531 aClass = type(aClass)
1533 raise ValError(_(u"type non supporté"))
1535 self.aClass = aClass
1538 return ufmt(_(tr(u"valeur d'instance de %s")), self.aClass.__name__)
1540 def verif_item(self, valeur):
1541 if not isinstance(valeur, self.aClass):
1546 class VerifTypeTuple(Valid, ListVal):
1548 def __init__(self, typeDesTuples):
1549 self.typeDesTuples = typeDesTuples
1550 Valid.__init__(self)
1554 return _(tr(u": verifie les types dans un tuple"))
1556 def info_erreur_liste(self):
1557 return _(tr(u"Les types entres ne sont pas permis"))
1559 def default(self, valeur):
1560 # if valeur in self.liste : raise ValError("%s est un doublon" %
1567 def convert_item(self, valeur):
1568 if len(valeur) != len(self.typeDesTuples):
1570 ufmt(_(tr(u"%s devrait etre de type %s ")), valeur, self.typeDesTuples))
1571 for i in range(len(valeur)):
1572 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1575 ufmt(_(tr(u"%s devrait etre de type %s ")), valeur, self.typeDesTuples))
1578 def verif_item(self, valeur):
1580 if len(valeur) != len(self.typeDesTuples):
1582 for i in range(len(valeur)):
1583 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1590 def verifType(self, valeur, type_permis):
1591 if type_permis == 'R':
1592 if type(valeur) in (types.IntType, types.FloatType, types.LongType):
1594 elif type_permis == 'I':
1595 if type(valeur) in (types.IntType, types.LongType):
1597 elif type_permis == 'C':
1598 if self.is_complexe(valeur):
1600 elif type_permis == 'TXM':
1601 if type(valeur) == types.StringType:
1605 def verif(self, valeur):
1606 if type(valeur) in (types.ListType, types.TupleType):
1607 liste = list(valeur)
1609 if self.verif_item(val) != 1:
1614 class VerifExiste(ListVal):
1617 fonctionne avec into
1618 Met une liste à jour selon les mot clefs existant
1619 exemple si into = ("A","B","C")
1620 si au niveau N du JDC les objets "A" et "C" existe
1621 alors la liste des into deviendra ( "A","C")
1623 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1624 niveauVerif est defini par rapport au Noeud :
1625 exemple niveauVerif = 1 : on verifie les freres
1626 niveauVerif = 2 : on verifie les oncles..
1629 def __init__(self, niveauVerif):
1630 ListVal.__init__(self)
1631 self.niveauVerif = niveauVerif
1633 self.listeDesFreres = ()
1634 self.fonctions = ('verifie_liste', 'set_MCSimp')
1639 def verifie_liste(self, liste):
1640 self.set_MCSimp(self.MCSimp)
1642 if not(item in self.listeDesFreres):
1646 def verif_item(self, valeur):
1647 self.set_MCSimp(self.MCSimp)
1648 if valeur in self.listeDesFreres:
1652 def set_MCSimp(self, MCSimp):
1653 self.MCSimp = MCSimp
1654 k = self.niveauVerif
1660 # on met la liste à jour
1661 parent.forceRecalcul = self.niveauVerif
1662 self.listeDesFreres = parent.liste_mc_presents()
1664 def convert_item(self, valeur):
1665 if valeur in self.listeDesFreres:
1668 ufmt(_(tr(u"%s n'est pas dans %s")), valeur, self.listeDesFreres))
1671 class RegExpVal(ListVal):
1674 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1677 errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1679 def __init__(self, pattern):
1680 self.pattern = pattern
1681 self.compiled_regexp = re.compile(pattern)
1684 return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
1686 def verif_item(self, valeur):
1687 if self.compiled_regexp.match(valeur):
1690 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1692 def convert_item(self, valeur):
1693 if self.compiled_regexp.match(valeur):
1696 raise ValError(self.errormsg %
1697 {"value": valeur, "pattern": self.pattern})
1700 class FileExtVal(RegExpVal):
1703 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1706 def __init__(self, ext):
1708 self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1710 #RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
1711 #PNPN Modif pour Adao
1712 #RegExpVal.__init__(self, "^[\S]+\.%s$" % self.ext
1713 RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
1717 return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext