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")), repr(obj), into))
278 # on est dans le cas d'un ensemble continu de valeurs possibles
280 if is_float_or_int(obj):
285 if obj < val_min or obj > val_max:
288 _(tr(u"La valeur : %s est en dehors du domaine de validite [ %s , %s ]")),
289 repr(obj), self.val_min, self.val_max))
294 # exemple de classe pour verificateur de type
295 # on utilise des instances de classe comme type (typ=MinStr(3,6), par
298 def __init__(self, min, max):
302 def __convert__(self, valeur):
303 if is_str(valeur) and self.min <= len(valeur) <= self.max:
307 _(tr(u"%s n'est pas une chaine de longueur comprise entre %s et %s")),
308 valeur, self.min, self.max))
311 return ufmt(_(tr(u"TXM de longueur entre %s et %s")), self.min, self.max)
314 class Valid(PProtocol):
317 Cette classe est la classe mere des validateurs Accas
318 Elle doit etre derivee
319 Elle presente la signature des methodes indispensables pour son bon
320 fonctionnement et dans certains cas leur comportement par défaut.
322 @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
323 @type cata_info: C{string}
327 def __init__(self, **args):
328 PProtocol.__init__(self, "valid", **args)
332 Cette methode retourne une chaine de caractères informative sur
333 la validation demandée par le validateur. Elle est utilisée
334 pour produire le compte-rendu de validité du mot clé associé.
336 return _(u"valeur valide")
340 Cette methode retourne une chaine de caractère qui permet
341 de construire un message d'aide en ligne.
342 En général, le message retourné est le meme que celui retourné par la
347 def info_erreur_item(self):
349 Cette méthode permet d'avoir un message d'erreur pour un item
350 dans une liste dans le cas ou le validateur fait des vérifications
351 sur les items d'une liste. Si le validateur fait seulement des
352 vérifications sur la liste elle meme et non sur ses items, la méthode
353 doit retourner une chaine vide.
357 def info_erreur_liste(self):
359 Cette méthode a un comportement complémentaire de celui de
360 info_erreur_item. Elle retourne un message d'erreur lié uniquement
361 aux vérifications sur la liste elle meme et pas sur ses items.
362 Dans le cas où le validateur ne fait pas de vérification sur des
363 listes, elle retourne une chaine vide
367 def verif(self, valeur):
369 Cette methode sert a verifier si la valeur passee en argument est consideree
370 comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
371 (valide) sinon 0 (invalide).
373 @type valeur: tout type python
374 @param valeur: valeur du mot cle a valider
376 @return: indicateur de validite 1 (valide) ou 0 (invalide)
378 raise NotImplementedError("Must be implemented")
380 def verif_item(self, valeur):
382 La methode verif du validateur effectue une validation complete de
383 la valeur. valeur peut etre un scalaire ou une liste. Le validateur
384 doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
385 methode is_list doit retourner 1).
386 La methode valid_item sert pour effectuer des validations partielles
387 de liste. Elle doit uniquement verifier la validite d'un item de
388 liste mais pas les caracteristiques de la liste.
392 def valide_liste_partielle(self, liste_courante):
394 Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
395 ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
396 veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
398 En général un validateur effectue la meme validation pour les listes partielles et les
401 return self.verif(liste_courante)
403 def verif_cata(self):
405 Cette methode sert a realiser des verifications du validateur lui meme.
406 Elle est facultative et retourne 1 (valide) par defaut.
407 Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
408 parametres de definition ne sont pas corrects.
409 La raison de l'invalidite est stockee dans l'attribut cata_info.
412 @return: indicateur de validite 1 (valide) ou 0 (invalide)
418 Cette méthode retourne un entier qui indique si le validateur
419 permet les listes (valeur 1) ou ne les permet pas (valeur 0).
420 Par défaut, un validateur n'autorise que des scalaires.
426 Cette méthode retourne un entier qui indique si le validateur
427 propose une liste de choix (valeur 1) ou n'en propose pas.
428 Par défaut, un validateur n'en propose pas.
432 def get_into(self, liste_courante=None, into_courant=None):
434 Cette méthode retourne la liste de choix proposée par le validateur.
435 Si le validateur ne propose pas de liste de choix, la méthode
437 L'argument d'entrée liste_courante, s'il est différent de None, donne
438 la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
439 méthode get_into doit calculer la liste des choix en en tenant
440 compte. Par exemple, si le validateur n'autorise pas les répétitions,
441 la liste des choix retournée ne doit pas contenir les choix déjà
442 contenus dans liste_courante.
443 L'argument d'entrée into_courant, s'il est différent de None, donne
444 la liste des choix proposés par d'autres validateurs. Dans ce cas,
445 la méthode get_into doit calculer la liste des choix à retourner
446 en se limitant à cette liste initiale. Par exemple, si into_courant
447 vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
448 la méthode ne doit retourner que (3,).
450 La méthode get_into peut retourner une liste vide [], ce qui veut
451 dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
452 peut etre normale : l''utilisateur a utilisé tous les choix, ou
453 résulter d'une incohérence des validateurs :
454 choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
455 faire la différence entre ces deux situations.
460 class ListVal(Valid):
463 Cette classe sert de classe mère pour tous les validateurs qui acceptent
470 def get_into(self, liste_courante=None, into_courant=None):
472 Cette méthode get_into effectue un traitement général qui consiste
473 a filtrer la liste de choix into_courant, si elle existe, en ne
474 conservant que les valeurs valides (appel de la méthode valid).
476 if into_courant is None:
480 for e in into_courant:
482 liste_choix.append(e)
485 def convert(self, valeur):
487 Méthode convert pour les validateurs de listes. Cette méthode
488 fait appel à la méthode convert_item sur chaque élément de la
491 if is_sequence(valeur):
493 self.convert_item(val)
496 return self.convert_item(valeur)
498 def verif(self, valeur):
500 Méthode verif pour les validateurs de listes. Cette méthode
501 fait appel à la méthode verif_item sur chaque élément de la
502 liste. Si valeur est un paramètre, on utilise sa valeur effective
505 if is_sequence(valeur):
507 if not self.verif_item(val):
511 return self.verif_item(valeur)
514 class Compulsory(ListVal):
516 Validateur operationnel
517 Verification de la présence obligatoire d'un élément dans une liste
521 def __init__(self, elem=()):
522 if not is_sequence(elem):
524 Valid.__init__(self, elem=elem)
529 return ufmt(_(tr(u"valeur %s obligatoire")), `self.elem`)
531 def default(self, valeur, elem):
534 def verif_item(self, valeur):
537 def convert(self, valeur):
538 elem = list(self.elem)
545 ufmt(_(tr(u"%s ne contient pas les elements obligatoires : %s ")),
552 def verif(self, valeur):
553 if not is_sequence(valeur):
557 for val in self.elem:
562 def info_erreur_item(self):
563 return _(u"La valeur n'est pas dans la liste des choix possibles")
566 class Together(ListVal):
568 Validateur operationnel
569 si un des éléments est présent les autres doivent aussi l'être
573 def __init__(self, elem=()):
574 if not is_sequence(elem):
576 Valid.__init__(self, elem=elem)
581 return ufmt(_(tr(u"%s present ensemble")), `self.elem`)
583 def default(self, valeur, elem):
586 def verif_item(self, valeur):
589 def convert(self, valeur):
590 elem = list(self.elem)
593 if v in elem: elem.remove(v)
594 if ( len(elem) == 0 ): return valeur
595 if len(elem) != len(list(self.elem)) :
596 raise ValError( ufmt(_(tr(u"%s ne contient pas les elements devant etre presents ensemble: %s ")), valeur, elem))
602 def verif(self, valeur):
603 if not is_sequence(valeur):
608 for val in self.elem:
609 if val in liste: compte += 1
610 if ( compte == 0 ): return 1
611 if ( compte != len( list(self.elem) ) ): return 0
614 def info_erreur_item(self):
615 return _(u"La valeur n'est pas dans la liste des choix possibles")
618 class Absent(ListVal):
620 Validateur operationnel
621 si un des éléments est présent non valide
625 def __init__(self, elem=()):
626 if not is_sequence(elem):
628 Valid.__init__(self, elem=elem)
633 return ufmt(_(tr(u"%s absent")), `self.elem`)
635 def default(self, valeur, elem):
638 def verif_item(self, valeur):
641 def convert(self, valeur):
642 elem = list(self.elem)
646 raise ValError( ufmt(_(tr(u"%s n'est pas autorise : %s ")), v, elem))
652 def verif(self, valeur):
653 if not is_sequence(valeur):
657 for val in self.elem:
658 if val in liste: return 0
661 def info_erreur_item(self):
662 return _(u"La valeur n'est pas dans la liste des choix possibles")
665 class NoRepeat(ListVal):
667 Validateur operationnel
668 Verification d'absence de doublons dans la liste.
675 return _(u": pas de présence de doublon dans la liste")
677 def info_erreur_liste(self):
678 return _(u"Les doublons ne sont pas permis")
680 def default(self, valeur):
681 if valeur in self.liste:
682 raise ValError(ufmt(_(tr(u"%s est un doublon")), valeur))
685 def convert(self, valeur):
692 def verif_item(self, valeur):
695 def verif(self, valeur):
696 if is_sequence(valeur):
699 if liste.count(val) != 1:
705 def get_into(self, liste_courante=None, into_courant=None):
707 Methode get_into spécifique pour validateur NoRepeat, on retourne
708 une liste de choix qui ne contient aucune valeur de into_courant
709 déjà contenue dans liste_courante
711 if into_courant is None:
715 for e in into_courant:
718 if liste_courante is not None and e in liste_courante:
720 liste_choix.append(e)
724 class LongStr(ListVal):
727 Validateur operationnel
728 Verification de la longueur d une chaine
731 def __init__(self, low, high):
732 ListVal.__init__(self, low=low, high=high)
738 return ufmt(_(tr(u"longueur de la chaine entre %s et %s")), self.low, self.high)
740 def info_erreur_item(self):
741 return _(tr(u"Longueur de la chaine incorrecte"))
743 def convert(self, valeur):
748 def verif_item(self, valeur):
755 def default(self, valeur, low, high):
756 if not is_str(valeur):
757 raise ValError(ufmt(_(tr(u"%s n'est pas une chaine")), repr(valeur)))
758 if valeur[0] == "'" and valeur[-1] == "'":
761 if len(valeur) < low or len(valeur) > high:
763 ufmt(_(tr(u"%s n'est pas de la bonne longueur")), repr(valeur)))
767 class OnlyStr(ListVal):
770 Validateur operationnel
771 Valide que c'est une chaine
775 ListVal.__init__(self)
779 return _(u"regarde si c'est une chaine")
781 def info_erreur_item(self):
782 return _(u"Ce n'est pas une chaine")
784 def convert(self, valeur):
789 def verif_item(self, valeur):
796 def default(self, valeur):
797 if not is_str(valeur):
798 raise ValError(ufmt(_(tr(u"%s n'est pas une chaine")), repr(valeur)))
802 class OrdList(ListVal):
805 Validateur operationnel
806 Verification qu'une liste est croissante ou decroissante
809 def __init__(self, ord):
810 ListVal.__init__(self, ord=ord)
815 return ufmt(_(tr(u"liste %s")), self.ord)
817 def info_erreur_liste(self):
818 return ufmt(_(tr(u"La liste doit etre en ordre %s")), self.ord)
820 def convert(self, valeur):
827 def default(self, valeur, ord):
828 if self.ord == 'croissant':
829 if self.val is not None and valeur < self.val:
831 ufmt(_(tr(u"%s n'est pas par valeurs croissantes")), repr(self.liste)))
832 elif self.ord == 'decroissant':
833 if self.val is not None and valeur > self.val:
835 ufmt(_(tr(u"%s n'est pas par valeurs decroissantes")), repr(self.liste)))
839 def verif_item(self, valeur):
842 def get_into(self, liste_courante=None, into_courant=None):
844 Methode get_into spécifique pour validateur OrdList, on retourne
845 une liste de choix qui ne contient aucune valeur de into_courant
846 dont la valeur est inférieure à la dernière valeur de
847 liste_courante, si elle est différente de None.
849 if into_courant is None:
851 elif not liste_courante:
855 last_val = liste_choix[-1]
856 for e in into_courant:
857 if self.ord == 'croissant' and e <= last_val:
859 if self.ord == 'decroissant' and e >= last_val:
861 liste_choix.append(e)
868 Validateur operationnel
869 Cette classe est un validateur qui controle une liste de validateurs
870 Elle verifie qu'au moins un des validateurs de la liste valide la valeur
873 def __init__(self, validators=()):
874 if not is_sequence(validators):
875 validators = (validators,)
877 for validator in validators:
878 if type(validator) == types.FunctionType:
879 self.validators.append(FunctionVal(validator))
881 self.validators.append(validator)
885 return "\n ou ".join([v.info() for v in self.validators])
887 def convert(self, valeur):
888 for validator in self.validators:
890 return validator.convert(valeur)
893 raise ValError(ufmt(_(tr(u"%s n'est pas du bon type")), repr(valeur)))
895 def info_erreur_item(self):
897 for v in self.validators:
898 err = v.info_erreur_item()
901 chaine = " \n ou ".join(l)
904 def info_erreur_liste(self):
906 for v in self.validators:
907 err = v.info_erreur_liste()
910 chaine = " \n ou ".join(l)
915 Si plusieurs validateurs sont reliés par un OU
916 il suffit qu'un seul des validateurs attende une liste
917 pour qu'on considère que leur union attend une liste.
919 for validator in self.validators:
920 v = validator.is_list()
925 def verif(self, valeur):
926 for validator in self.validators:
927 v = validator.verif(valeur)
932 def verif_item(self, valeur):
933 for validator in self.validators:
934 v = validator.verif_item(valeur)
939 def verif_cata(self):
941 for validator in self.validators:
942 v = validator.verif_cata()
944 infos.append(validator.cata_info)
946 self.cata_info = "\n".join(infos)
953 Dans le cas ou plusieurs validateurs sont reliés par un OU
954 il faut que tous les validateurs proposent un choix pour
955 qu'on considère que leur union propose un choix.
956 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
957 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
959 for validator in self.validators:
960 v = validator.has_into()
965 def get_into(self, liste_courante=None, into_courant=None):
967 Dans le cas ou plusieurs validateurs sont reliés par un OU
968 tous les validateurs doivent proposer un choix pour
969 qu'on considère que leur union propose un choix. Tous les choix
970 proposés par les validateurs sont réunis (opérateur d'union).
971 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
972 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
976 for validator in self.validators:
977 v_into = validator.get_into(liste_courante, into_courant)
980 validator_into.extend(v_into)
981 return validator_into
983 def valide_liste_partielle(self, liste_courante=None):
985 Méthode de validation de liste partielle pour le validateur Or.
986 Si un des validateurs gérés par le validateur Or considère la
987 liste comme valide, le validateur Or la considère comme valide.
989 for validator in self.validators:
990 v = validator.valide_liste_partielle(liste_courante)
999 Validateur operationnel
1000 Cette classe est un validateur qui controle une liste de validateurs
1001 Elle verifie que tous les validateurs de la liste valident la valeur
1004 def __init__(self, validators=()):
1005 if not is_sequence(validators):
1006 validators = (validators,)
1007 self.validators = []
1008 for validator in validators:
1009 if type(validator) == types.FunctionType:
1010 self.validators.append(FunctionVal(validator))
1012 self.validators.append(validator)
1013 if hasattr(validator, 'fonctions'):
1014 for fonction in validator.fonctions:
1015 f = getattr(validator, fonction)
1016 setattr(self, fonction, f)
1020 return "\n et ".join([v.info() for v in self.validators])
1022 def convert(self, valeur):
1023 for validator in self.validators:
1024 valeur = validator.convert(valeur)
1027 def info_erreur_item(self):
1030 for v in self.validators:
1031 if v.info_erreur_item() != " ":
1033 chaine = v.info_erreur_item()
1036 chaine = chaine + " \n et " + v.info_erreur_item()
1039 def info_erreur_liste(self):
1041 for v in self.validators:
1042 if v.info_erreur_liste() != " ":
1044 chaine = v.info_erreur_liste()
1047 chaine = chaine + " \n et " + v.info_erreur_liste()
1050 def verif(self, valeur):
1051 for validator in self.validators:
1052 v = validator.verif(valeur)
1054 self.local_info = validator.info()
1058 def verif_item(self, valeur):
1059 for validator in self.validators:
1060 v = validator.verif_item(valeur)
1062 # L'info n'est probablement pas la meme que pour verif ???
1063 self.local_info = validator.info()
1067 def verif_cata(self):
1069 for validator in self.validators:
1070 v = validator.verif_cata()
1072 infos.append(validator.cata_info)
1074 self.cata_info = "\n".join(infos)
1079 def valide_liste_partielle(self, liste_courante=None):
1081 Méthode de validation de liste partielle pour le validateur And.
1082 Tous les validateurs gérés par le validateur And doivent considérer
1083 la liste comme valide, pour que le validateur And la considère
1086 for validator in self.validators:
1087 v = validator.valide_liste_partielle(liste_courante)
1094 Si plusieurs validateurs sont reliés par un ET
1095 il faut que tous les validateurs attendent une liste
1096 pour qu'on considère que leur intersection attende une liste.
1097 Exemple Range(2,5) ET Card(1) n'attend pas une liste
1098 Range(2,5) ET Pair attend une liste
1100 for validator in self.validators:
1101 v = validator.is_list()
1108 Dans le cas ou plusieurs validateurs sont reliés par un ET
1109 il suffit qu'un seul validateur propose un choix pour
1110 qu'on considère que leur intersection propose un choix.
1111 Exemple : Enum(1,2,3) ET entier pair, propose un choix
1112 En revanche, entier pair ET superieur à 10 ne propose pas de choix
1114 for validator in self.validators:
1115 v = validator.has_into()
1120 def get_into(self, liste_courante=None, into_courant=None):
1122 Dans le cas ou plusieurs validateurs sont reliés par un ET
1123 il suffit qu'un seul validateur propose un choix pour
1124 qu'on considère que leur intersection propose un choix. Tous les
1125 choix proposés par les validateurs sont croisés (opérateur
1127 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
1128 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
1130 for validator in self.validators:
1131 into_courant = validator.get_into(liste_courante, into_courant)
1132 if into_courant in ([], None):
1137 def do_liste(validators):
1139 Convertit une arborescence de validateurs en OrVal ou AndVal
1140 validators est une liste de validateurs ou de listes ou de tuples
1143 for validator in validators:
1144 if type(validator) == types.FunctionType:
1145 valids.append(FunctionVal(validator))
1146 elif type(validator) is tuple:
1147 valids.append(OrVal(do_liste(validator)))
1148 elif type(validator) is list:
1149 valids.append(AndVal(do_liste(validator)))
1151 valids.append(validator)
1155 def validatorFactory(validator):
1156 if type(validator) == types.FunctionType:
1157 return FunctionVal(validator)
1158 elif type(validator) is tuple:
1159 return OrVal(do_liste(validator))
1160 elif type(validator) is list:
1161 return AndVal(do_liste(validator))
1165 # Ci-dessous : exemples de validateur (peu testés)
1168 class RangeVal(ListVal):
1171 Exemple de classe validateur : verification qu'une valeur
1172 est dans un intervalle.
1173 Pour une liste on verifie que tous les elements sont
1175 Susceptible de remplacer les attributs "vale_min" "vale_max"
1179 def __init__(self, low, high):
1182 self.cata_info = ufmt(_(tr(u"%s doit etre inferieur a %s")), low, high)
1185 return ufmt(_(tr(u"valeur dans l'intervalle %s , %s")), self.low, self.high)
1187 def convert_item(self, valeur):
1188 if valeur > self.low and valeur < self.high:
1190 raise ValError(ufmt(_(tr(u"%s devrait etre comprise entre %s et %s")),
1191 valeur, self.low, self.high))
1193 def verif_item(self, valeur):
1194 return valeur > self.low and valeur < self.high
1196 def info_erreur_item(self):
1197 return ufmt(_(tr(u"La valeur doit etre comprise entre %s et %s")), self.low, self.high)
1199 def verif_cata(self):
1200 if self.low > self.high:
1205 class CardVal(Valid):
1208 Exemple de classe validateur : verification qu'une liste est
1209 d'une longueur superieur a un minimum (min) et inferieure
1211 Susceptible de remplacer les attributs "min" "max" dans les
1215 def __init__(self, min='**', max='**'):
1218 self.cata_info = ufmt(_(tr(u"%s doit etre inferieur a %s")), min, max)
1221 return ufmt(_(tr(u"longueur de liste comprise entre %s et %s")), self.min, self.max)
1223 def info_erreur_liste(self):
1225 _(tr(u"Le cardinal de la liste doit etre compris entre %s et %s")),
1229 return self.max == '**' or self.max > 1
1231 def get_into(self, liste_courante=None, into_courant=None):
1232 if into_courant is None:
1234 elif liste_courante is None:
1236 elif self.max == '**':
1238 elif len(liste_courante) < self.max:
1243 def convert(self, valeur):
1244 if is_sequence(valeur):
1246 elif valeur is None:
1250 if self.max != '**' and l > self.max:
1252 ufmt(_(tr(u"%s devrait etre de longueur inferieure a %s")), valeur, self.max))
1253 if self.min != '**' and l < self.min:
1255 ufmt(_(tr(u"%s devrait etre de longueur superieure a %s")), valeur, self.min))
1258 def verif_item(self, valeur):
1261 def verif(self, valeur):
1262 if is_sequence(valeur):
1263 if self.max != '**' and len(valeur) > self.max:
1265 if self.min != '**' and len(valeur) < self.min:
1269 if self.max != '**' and 1 > self.max:
1271 if self.min != '**' and 1 < self.min:
1275 def verif_cata(self):
1276 if self.min != '**' and self.max != '**' and self.min > self.max:
1280 def valide_liste_partielle(self, liste_courante=None):
1282 if liste_courante != None:
1283 if len(liste_courante) > self.max:
1288 class PairVal(ListVal):
1291 Exemple de classe validateur : verification qu'une valeur
1293 Pour une liste on verifie que tous les elements sont
1298 ListVal.__init__(self)
1302 return _(u"valeur paire")
1304 def info_erreur_item(self):
1305 return _(u"La valeur saisie doit etre paire")
1307 def convert(self, valeur):
1312 ufmt(_(tr(u"%s contient des valeurs non paires")), repr(valeur)))
1315 def default(self, valeur):
1318 def verif_item(self, valeur):
1319 if type(valeur) not in (int, long):
1321 return valeur % 2 == 0
1323 def verif(self, valeur):
1324 if is_sequence(valeur):
1335 class EnumVal(ListVal):
1338 Exemple de classe validateur : verification qu'une valeur
1339 est prise dans une liste de valeurs.
1340 Susceptible de remplacer l attribut "into" dans les catalogues
1343 def __init__(self, into=()):
1344 if not is_sequence(into):
1350 return "valeur dans %s" % `self.into`
1352 def convert_item(self, valeur):
1353 if valeur in self.into:
1356 ufmt(_(tr(u"%s contient des valeurs hors des choix possibles: %s ")),
1359 def verif_item(self, valeur):
1360 if valeur not in self.into:
1367 def get_into(self, liste_courante=None, into_courant=None):
1368 if into_courant is None:
1369 liste_choix = list(self.into)
1372 for e in into_courant:
1374 liste_choix.append(e)
1377 def info_erreur_item(self):
1378 return _(u"La valeur n'est pas dans la liste des choix possibles")
1381 def ImpairVal(valeur):
1383 Exemple de validateur
1384 Cette fonction est un validateur. Elle verifie que la valeur passee
1385 est bien un nombre impair.
1387 if is_sequence(valeur):
1397 ImpairVal.info = "valeur impaire"
1403 Exemple de validateur
1404 Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1405 que la somme des cles A et B vaut une valeur donnee
1406 en parametre du validateur
1409 def __init__(self, somme=10):
1414 return ufmt(_(tr(u"valeur %s pour la somme des cles A et B ")), self.somme)
1416 def verif(self, valeur):
1417 if is_sequence(valeur):
1419 if not val.has_key("A"):
1421 if not val.has_key("B"):
1423 if val["A"] + val["B"] != self.somme:
1427 if not valeur.has_key("A"):
1429 if not valeur.has_key("B"):
1431 if valeur["A"] + valeur["B"] != self.somme:
1436 class FunctionVal(Valid):
1439 Exemple de validateur
1440 Cette classe est un validateur qui est initialise avec une fonction
1443 def __init__(self, function):
1444 self.function = function
1447 return self.function.info
1449 def verif(self, valeur):
1450 return self.function(valeur)
1452 def verif_item(self, valeur):
1453 return self.function(valeur)
1455 def convert(self, valeur):
1458 # MC ca ne devrait plus servir !
1459 CoercableFuncs = {types.IntType: int,
1460 types.LongType: long,
1461 types.FloatType: float,
1462 types.ComplexType: complex,
1463 types.UnicodeType: unicode}
1466 class TypeVal(ListVal):
1469 Exemple de validateur
1470 Cette classe est un validateur qui controle qu'une valeur
1471 est bien du type Python attendu.
1472 Pour une liste on verifie que tous les elements sont du bon type.
1473 Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1474 alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1477 def __init__(self, aType):
1478 # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1479 # type(1) == int;type(0.2)==float;etc.
1480 if type(aType) != types.TypeType:
1484 self.coerce = CoercableFuncs[aType]
1486 self.coerce = self.identity
1489 return ufmt(_(tr(u"valeur de %s")), self.aType)
1491 def identity(self, value):
1492 if type(value) == self.aType:
1496 def convert_item(self, valeur):
1497 return self.coerce(valeur)
1499 def verif_item(self, valeur):
1507 class InstanceVal(ListVal):
1510 Exemple de validateur
1511 Cette classe est un validateur qui controle qu'une valeur est
1512 bien une instance (au sens Python) d'une classe
1513 Pour une liste on verifie chaque element de la liste
1516 def __init__(self, aClass):
1517 # Si aClass est une classe on la memorise dans self.aClass
1518 # sinon c'est une instance dont on memorise la classe
1519 if type(aClass) == types.InstanceType:
1520 # instance ancienne mode
1521 aClass = aClass.__class__
1522 elif type(aClass) == types.ClassType:
1523 # classe ancienne mode
1525 elif type(aClass) == type:
1526 # classe nouvelle mode
1528 elif isinstance(aClass, object):
1529 # instance nouvelle mode
1530 aClass = type(aClass)
1532 raise ValError(_(u"type non supporté"))
1534 self.aClass = aClass
1537 return ufmt(_(tr(u"valeur d'instance de %s")), self.aClass.__name__)
1539 def verif_item(self, valeur):
1540 if not isinstance(valeur, self.aClass):
1545 class VerifTypeTuple(Valid, ListVal):
1547 def __init__(self, typeDesTuples):
1548 self.typeDesTuples = typeDesTuples
1549 Valid.__init__(self)
1553 return _(tr(u": verifie les types dans un tuple"))
1555 def info_erreur_liste(self):
1556 return _(tr(u"Les types entres ne sont pas permis"))
1558 def default(self, valeur):
1559 # if valeur in self.liste : raise ValError("%s est un doublon" %
1566 def convert_item(self, valeur):
1567 if len(valeur) != len(self.typeDesTuples):
1569 ufmt(_(tr(u"%s devrait etre de type %s ")), valeur, self.typeDesTuples))
1570 for i in range(len(valeur)):
1571 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1574 ufmt(_(tr(u"%s devrait etre de type %s ")), valeur, self.typeDesTuples))
1577 def verif_item(self, valeur):
1579 if len(valeur) != len(self.typeDesTuples):
1581 for i in range(len(valeur)):
1582 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1589 def verifType(self, valeur, type_permis):
1590 if type_permis == 'R':
1591 if type(valeur) in (types.IntType, types.FloatType, types.LongType):
1593 elif type_permis == 'I':
1594 if type(valeur) in (types.IntType, types.LongType):
1596 elif type_permis == 'C':
1597 if self.is_complexe(valeur):
1599 elif type_permis == 'TXM':
1600 if type(valeur) == types.StringType:
1602 elif isinstance(valeur, type_permis):
1606 def verif(self, valeur):
1607 if type(valeur) in (types.ListType, types.TupleType):
1608 liste = list(valeur)
1610 if self.verif_item(val) != 1:
1615 class VerifExiste(ListVal):
1618 fonctionne avec into
1619 Met une liste à jour selon les mot clefs existant
1620 exemple si into = ("A","B","C")
1621 si au niveau N du JDC les objets "A" et "C" existe
1622 alors la liste des into deviendra ( "A","C")
1624 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1625 niveauVerif est defini par rapport au Noeud :
1626 exemple niveauVerif = 1 : on verifie les freres
1627 niveauVerif = 2 : on verifie les oncles..
1630 def __init__(self, niveauVerif):
1631 ListVal.__init__(self)
1632 self.niveauVerif = niveauVerif
1634 self.listeDesFreres = ()
1635 self.fonctions = ('verifie_liste', 'set_MCSimp')
1640 def verifie_liste(self, liste):
1641 self.set_MCSimp(self.MCSimp)
1643 if not(item in self.listeDesFreres):
1647 def verif_item(self, valeur):
1648 self.set_MCSimp(self.MCSimp)
1649 if valeur in self.listeDesFreres:
1653 def set_MCSimp(self, MCSimp):
1654 self.MCSimp = MCSimp
1655 k = self.niveauVerif
1661 # on met la liste à jour
1662 parent.forceRecalcul = self.niveauVerif
1663 self.listeDesFreres = parent.liste_mc_presents()
1665 def convert_item(self, valeur):
1666 if valeur in self.listeDesFreres:
1669 ufmt(_(tr(u"%s n'est pas dans %s")), valeur, self.listeDesFreres))
1672 class RegExpVal(ListVal):
1675 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1678 errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1680 def __init__(self, pattern):
1681 self.pattern = pattern
1682 self.compiled_regexp = re.compile(pattern)
1685 return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
1687 def verif_item(self, valeur):
1688 if self.compiled_regexp.match(valeur):
1691 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1693 def convert_item(self, valeur):
1694 if self.compiled_regexp.match(valeur):
1697 raise ValError(self.errormsg %
1698 {"value": valeur, "pattern": self.pattern})
1701 class FileExtVal(RegExpVal):
1704 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1707 def __init__(self, ext):
1709 self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1711 #RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
1712 #PNPN Modif pour Adao
1713 #RegExpVal.__init__(self, "^[\S]+\.%s$" % self.ext
1714 RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
1718 return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext