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 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):
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(": verifie les types dans un tuple"))
1556 def info_erreur_liste(self):
1557 return _(tr("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:
1603 elif isinstance(valeur, type_permis):
1607 def verif(self, valeur):
1608 if type(valeur) in (types.ListType, types.TupleType):
1609 liste = list(valeur)
1611 if self.verif_item(val) != 1:
1616 class VerifExiste(ListVal):
1619 fonctionne avec into
1620 Met une liste à jour selon les mot clefs existant
1621 exemple si into = ("A","B","C")
1622 si au niveau N du JDC les objets "A" et "C" existe
1623 alors la liste des into deviendra ( "A","C")
1625 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1626 niveauVerif est defini par rapport au Noeud :
1627 exemple niveauVerif = 1 : on verifie les freres
1628 niveauVerif = 2 : on verifie les oncles..
1631 def __init__(self, niveauVerif):
1632 ListVal.__init__(self)
1633 self.niveauVerif = niveauVerif
1635 self.listeDesFreres = ()
1636 self.fonctions = ('verifie_liste', 'set_MCSimp')
1641 def verifie_liste(self, liste):
1642 self.set_MCSimp(self.MCSimp)
1644 if not(item in self.listeDesFreres):
1648 def verif_item(self, valeur):
1649 self.set_MCSimp(self.MCSimp)
1650 if valeur in self.listeDesFreres:
1654 def set_MCSimp(self, MCSimp):
1655 self.MCSimp = MCSimp
1656 k = self.niveauVerif
1662 # on met la liste à jour
1663 parent.forceRecalcul = self.niveauVerif
1664 self.listeDesFreres = parent.liste_mc_presents()
1666 def convert_item(self, valeur):
1667 if valeur in self.listeDesFreres:
1670 ufmt(_(tr(u"%s n'est pas dans %s")), valeur, self.listeDesFreres))
1673 class RegExpVal(ListVal):
1676 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1679 errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1681 def __init__(self, pattern):
1682 self.pattern = pattern
1683 self.compiled_regexp = re.compile(pattern)
1686 return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
1688 def verif_item(self, valeur):
1689 if self.compiled_regexp.match(valeur):
1692 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1694 def convert_item(self, valeur):
1695 if self.compiled_regexp.match(valeur):
1698 raise ValError(self.errormsg %
1699 {"value": valeur, "pattern": self.pattern})
1702 class FileExtVal(RegExpVal):
1705 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1708 def __init__(self, ext):
1710 self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1712 #RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
1713 #PNPN Modif pour Adao
1714 #RegExpVal.__init__(self, "^[\S]+\.%s$" % self.ext
1715 RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
1719 return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext
1722 def __init__(self,MotClef ):
1723 self.MotClef=MotClef
1726 def convert(self, lval):
1727 print "dans convert"
1728 try : valeur=lval[0]
1729 except : return lval
1731 parent= self.MCSimp.parent
1732 if hasattr(parent, 'inhibeValidator') and parent.inhibeValidator: return lval
1735 if parent.get_child(self.MotClef) == None : longueur=0
1736 else : longueur=len(parent.get_child(self.MotClef))
1738 pos=parent.get_index_child(self.MCSimp.nom)+1
1739 while longueur < valeur :
1740 parent.inhibeValidator=1
1741 parent.addentite(self.MotClef,pos)
1743 parent.inhibeValidator=0
1744 longueur=len(parent.get_child(self.MotClef))
1746 if longueur > valeur :
1747 parent.inhibeValide=1
1748 parentObj=parent.get_child(self.MotClef)
1749 obj=parent.get_child(self.MotClef)[-1]
1750 parentObj.suppentite(obj)
1751 longueur=len(parent.get_child(self.MotClef))
1752 parent.inhibeValide=0
1756 return "Cree le bon nombre de Mot %s" % self.MotClef
1758 def verif_item(self, valeur):
1761 def set_MCSimp(self, MCSimp):
1762 #print "dans set_MCSimp"