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
27 from __future__ import absolute_import
28 from __future__ import print_function
30 from builtins import str
31 from builtins import range
32 from builtins import object
38 from .N_ASSD import ASSD
39 from .N_types import is_int, is_float_or_int, is_complex, is_number, is_str, is_sequence
40 from Extensions.i18n import tr
42 from six.moves import range
46 class ValError(Exception):
51 if hasattr(cls, "__mro__"):
54 for base in cls.__bases__:
55 mro.extend(cls_mro(base))
59 class Protocol(object):
61 def __init__(self, name):
66 def register(self, T, A):
70 # (a) verifier si l'objet peut s'adapter au protocole
71 adapt = getattr(obj, '__adapt__', None)
73 # on demande à l'objet obj de réaliser lui-meme l'adaptation
76 # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
78 for T in cls_mro(obj.__class__):
79 if T in self.registry:
80 return self.registry[T](obj, self, **self.args)
82 # (c) utiliser l'adapteur par defaut
83 return self.default(obj, **self.args)
85 def default(self, obj, **args):
86 raise TypeError("Can't adapt %s to %s" %
87 (obj.__class__.__name__, self.name))
90 class PProtocol(Protocol):
92 """Verificateur de protocole paramétré (classe de base)"""
93 # Protocole paramétré. Le registre est unique pour toutes les instances.
94 # La methode register est une methode de classe
97 def __init__(self, name, **args):
101 def register(cls, T, A):
103 register = classmethod(register)
106 class ListProtocol(Protocol):
108 """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
110 def default(self, obj):
111 if type(obj) is tuple:
112 if len(obj) > 0 and obj[0] in ('RI', 'MP'):
113 # il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
117 elif type(obj) is list:
120 # pas de valeur affecte. La cardinalite vaut 0
123 # il s'agit d'une chaine. La cardinalite vaut 1
127 # si l'objet supporte len, on a la cardinalite
134 listProto = ListProtocol("list")
137 class TypeProtocol(PProtocol):
139 """Verificateur de type parmi une liste de types possibles"""
140 # pas de registre par instance. Registre unique pour toutes les instances
144 def __init__(self, name, typ=None):
145 PProtocol.__init__(self, name, typ=typ)
148 def default(self, obj, typ):
151 for type_permis in typ:
152 if type_permis == 'R':
153 if is_float_or_int(obj):
155 elif type_permis == 'I':
158 elif type_permis == 'C':
159 if self.is_complexe(obj):
161 elif type_permis == 'TXM':
164 elif type_permis == 'shell':
167 elif type_permis == 'Fichier':
170 if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj):
173 raise ValError( "%s n'est pas un fichier valide" % repr(obj))
175 raise ValError( "%s n'est pas un fichier valide" % repr(obj))
177 elif type_permis == 'FichierNoAbs':
179 if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")):
182 raise ValError( "%s n'est pas un fichier valide" % repr(obj))
184 elif type_permis == 'Repertoire':
187 if os.path.isdir(obj): return obj
188 else: raise ValError( "%s n'est pas un repertoire valide" % repr(obj))
190 raise ValError( "%s n'est pas un repertoire valide" % repr(obj))
191 elif type(type_permis) == type or isinstance(type_permis, type):
193 if self.is_object_from(obj, type_permis):
195 except Exception as err:
197 elif type(type_permis) == types.InstanceType or isinstance(type_permis, object):
199 if type_permis.__convert__(obj):
201 except Exception as err:
204 print(("Type non encore gere %s" %type_permis))
206 tr("%s (de type %s) n'est pas d'un type autorise: %s %s") % (repr(obj), type(obj), typ, err))
208 def is_complexe(self, valeur):
209 """ Retourne 1 si valeur est un complexe, 0 sinon """
210 if is_number(valeur):
211 # Pour permettre l'utilisation de complexes Python (accepte les
214 elif type(valeur) != tuple:
215 # On n'autorise pas les listes pour les complexes
217 elif len(valeur) != 3:
220 # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
221 # valeur suivie de 2 reels.
222 if valeur[0].strip() in ('RI', 'MP'):
224 v1 = reelProto.adapt(valeur[1]), reelProto.adapt(valeur[2])
231 def is_object_from(self, objet, classe):
233 Retourne 1 si objet est une instance de la classe classe, 0 sinon
235 convert = getattr(classe, '__convert__', None)
236 if convert is not None:
237 # classe verifie les valeurs
241 except ValueError as err:
245 # On accepte les instances de la classe et des classes derivees
246 return isinstance(objet, classe)
248 reelProto = TypeProtocol("reel", typ=('R',))
251 class CardProtocol(PProtocol):
253 """Verificateur de cardinalité """
254 # pas de registre par instance. Registre unique pour toutes les instances
257 def __init__(self, name, min=1, max=1):
258 PProtocol.__init__(self, name, min=min, max=max)
260 def default(self, obj, min, max):
262 if (length < min) or( length > max):
264 "Nombre d'arguments de %s incorrect (min = %s, max = %s)" % (repr(obj), min, max))
268 class IntoProtocol(PProtocol):
270 """Verificateur de choix possibles : liste discrète ou intervalle"""
271 # pas de registre par instance. Registre unique pour toutes les instances
274 def __init__(self, name, into=None, val_min=float('-inf'), val_max=float('inf')):
277 self, name, into=into, val_min=val_min, val_max=val_max)
278 self.val_min = val_min
279 self.val_max = val_max
281 def default(self, obj, into, val_min, val_max):
285 tr("La valeur : %s ne fait pas partie des choix possibles %s") % (repr(obj), into))
287 # on est dans le cas d'un ensemble continu de valeurs possibles
289 if is_float_or_int(obj):
294 if obj < val_min or obj > val_max:
296 tr("La valeur : %s est en dehors du domaine de validite [ %s , %s ]") %(repr(obj), self.val_min, self.val_max))
300 class MinStr(object):
301 # exemple de classe pour verificateur de type
302 # on utilise des instances de classe comme type (typ=MinStr(3,6), par
305 def __init__(self, min, max):
309 def __convert__(self, valeur):
310 if is_str(valeur) and self.min <= len(valeur) <= self.max: return valeur
312 "%s n'est pas une chaine de longueur comprise entre %s et %s" % (valeur, self.min, self.max))
315 return tr("TXM de longueur entre %s et %s" % (self.min, self.max))
318 class Valid(PProtocol):
321 Cette classe est la classe mere des validateurs Accas
322 Elle doit etre derivee
323 Elle presente la signature des methodes indispensables pour son bon
324 fonctionnement et dans certains cas leur comportement par défaut.
326 @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
331 def __init__(self, **args):
332 PProtocol.__init__(self, "valid", **args)
336 Cette methode retourne une chaine de caractères informative sur
337 la validation demandée par le validateur. Elle est utilisée
338 pour produire le compte-rendu de validité du mot clé associé.
340 return "valeur valide"
344 Cette methode retourne une chaine de caractère qui permet
345 de construire un message d'aide en ligne.
346 En général, le message retourné est le meme que celui retourné par la
351 def info_erreur_item(self):
353 Cette méthode permet d'avoir un message d'erreur pour un item
354 dans une liste dans le cas ou le validateur fait des vérifications
355 sur les items d'une liste. Si le validateur fait seulement des
356 vérifications sur la liste elle meme et non sur ses items, la méthode
357 doit retourner une chaine vide.
361 def info_erreur_liste(self):
363 Cette méthode a un comportement complémentaire de celui de
364 info_erreur_item. Elle retourne un message d'erreur lié uniquement
365 aux vérifications sur la liste elle meme et pas sur ses items.
366 Dans le cas où le validateur ne fait pas de vérification sur des
367 listes, elle retourne une chaine vide
371 def verif(self, valeur):
373 Cette methode sert a verifier si la valeur passee en argument est consideree
374 comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
375 (valide) sinon 0 (invalide).
377 @type valeur: tout type python
378 @param valeur: valeur du mot cle a valider
380 @return: indicateur de validite 1 (valide) ou 0 (invalide)
382 raise NotImplementedError("Must be implemented")
384 def verif_item(self, valeur):
386 La methode verif du validateur effectue une validation complete de
387 la valeur. valeur peut etre un scalaire ou une liste. Le validateur
388 doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
389 methode is_list doit retourner 1).
390 La methode valid_item sert pour effectuer des validations partielles
391 de liste. Elle doit uniquement verifier la validite d'un item de
392 liste mais pas les caracteristiques de la liste.
396 def valide_liste_partielle(self, liste_courante):
398 Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
399 ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
400 veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
402 En général un validateur effectue la meme validation pour les listes partielles et les
405 return self.verif(liste_courante)
407 def verif_cata(self):
409 Cette methode sert a realiser des verifications du validateur lui meme.
410 Elle est facultative et retourne 1 (valide) par defaut.
411 Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
412 parametres de definition ne sont pas corrects.
413 La raison de l'invalidite est stockee dans l'attribut cata_info.
416 @return: indicateur de validite 1 (valide) ou 0 (invalide)
422 Cette méthode retourne un entier qui indique si le validateur
423 permet les listes (valeur 1) ou ne les permet pas (valeur 0).
424 Par défaut, un validateur n'autorise que des scalaires.
430 Cette méthode retourne un entier qui indique si le validateur
431 propose une liste de choix (valeur 1) ou n'en propose pas.
432 Par défaut, un validateur n'en propose pas.
436 def get_into(self, liste_courante=None, into_courant=None):
438 Cette méthode retourne la liste de choix proposée par le validateur.
439 Si le validateur ne propose pas de liste de choix, la méthode
441 L'argument d'entrée liste_courante, s'il est différent de None, donne
442 la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
443 méthode get_into doit calculer la liste des choix en en tenant
444 compte. Par exemple, si le validateur n'autorise pas les répétitions,
445 la liste des choix retournée ne doit pas contenir les choix déjà
446 contenus dans liste_courante.
447 L'argument d'entrée into_courant, s'il est différent de None, donne
448 la liste des choix proposés par d'autres validateurs. Dans ce cas,
449 la méthode get_into doit calculer la liste des choix à retourner
450 en se limitant à cette liste initiale. Par exemple, si into_courant
451 vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
452 la méthode ne doit retourner que (3,).
454 La méthode get_into peut retourner une liste vide [], ce qui veut
455 dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
456 peut etre normale : l''utilisateur a utilisé tous les choix, ou
457 résulter d'une incohérence des validateurs :
458 choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
459 faire la différence entre ces deux situations.
464 class ListVal(Valid):
467 Cette classe sert de classe mère pour tous les validateurs qui acceptent
474 def get_into(self, liste_courante=None, into_courant=None):
476 Cette méthode get_into effectue un traitement général qui consiste
477 a filtrer la liste de choix into_courant, si elle existe, en ne
478 conservant que les valeurs valides (appel de la méthode valid).
480 if into_courant is None:
484 for e in into_courant:
486 liste_choix.append(e)
489 def convert(self, valeur):
491 Méthode convert pour les validateurs de listes. Cette méthode
492 fait appel à la méthode convert_item sur chaque élément de la
495 if is_sequence(valeur):
497 self.convert_item(val)
500 return self.convert_item(valeur)
502 def verif(self, valeur):
504 Méthode verif pour les validateurs de listes. Cette méthode
505 fait appel à la méthode verif_item sur chaque élément de la
506 liste. Si valeur est un paramètre, on utilise sa valeur effective
509 if is_sequence(valeur):
511 if not self.verif_item(val):
515 return self.verif_item(valeur)
518 class Compulsory(ListVal):
520 Validateur operationnel
521 Verification de la présence obligatoire d'un élément dans une liste
525 def __init__(self, elem=()):
526 if not is_sequence(elem):
528 Valid.__init__(self, elem=elem)
533 return (tr(u"valeur %s obligatoire") % self.elem)
535 def default(self, valeur, elem):
538 def verif_item(self, valeur):
541 def convert(self, valeur):
542 elem = list(self.elem)
549 tr("%s ne contient pas les elements obligatoires : %s ") % (valeur, elem))
555 def verif(self, valeur):
556 if not is_sequence(valeur):
560 for val in self.elem:
565 def info_erreur_item(self):
566 return tr("La valeur n'est pas dans la liste des choix possibles")
569 class Together(ListVal):
571 Validateur operationnel
572 si un des éléments est présent les autres doivent aussi l'être
576 def __init__(self, elem=()):
577 if not is_sequence(elem):
579 Valid.__init__(self, elem=elem)
584 return (tr("%s present ensemble") % self.elem)
586 def default(self, valeur, elem):
589 def verif_item(self, valeur):
592 def convert(self, valeur):
593 elem = list(self.elem)
596 if v in elem: elem.remove(v)
597 if ( len(elem) == 0 ): return valeur
598 if len(elem) != len(list(self.elem)) :
599 raise ValError(tr("%s ne contient pas les elements devant etre presents ensemble: %s ") %( valeur, elem))
605 def verif(self, valeur):
606 if not is_sequence(valeur):
611 for val in self.elem:
612 if val in liste: compte += 1
613 if ( compte == 0 ): return 1
614 if ( compte != len( list(self.elem) ) ): return 0
617 def info_erreur_item(self):
618 return tr("La valeur n'est pas dans la liste des choix possibles")
621 class Absent(ListVal):
623 Validateur operationnel
624 si un des éléments est présent non valide
628 def __init__(self, elem=()):
629 if not is_sequence(elem):
631 Valid.__init__(self, elem=elem)
636 return (tr("%s absent") % self.elem)
638 def default(self, valeur, elem):
641 def verif_item(self, valeur):
644 def convert(self, valeur):
645 elem = list(self.elem)
649 raise ValError(tr("%s n'est pas autorise : %s ")% (v, elem))
655 def verif(self, valeur):
656 if not is_sequence(valeur):
660 for val in self.elem:
661 if val in liste: return 0
664 def info_erreur_item(self):
665 return tr("La valeur n'est pas dans la liste des choix possibles")
668 class NoRepeat(ListVal):
670 Validateur operationnel
671 Verification d'absence de doublons dans la liste.
678 return tr("Pas de doublon dans la liste")
680 def info_erreur_liste(self):
681 return tr("Les doublons ne sont pas permis")
683 def default(self, valeur):
684 if valeur in self.liste:
685 raise ValError( tr("%s est un doublon") % valeur)
688 def convert(self, valeur):
695 def verif_item(self, valeur):
698 def verif(self, valeur):
699 if is_sequence(valeur):
702 if liste.count(val) != 1:
708 def get_into(self, liste_courante=None, into_courant=None):
710 Methode get_into spécifique pour validateur NoRepeat, on retourne
711 une liste de choix qui ne contient aucune valeur de into_courant
712 déjà contenue dans liste_courante
714 if into_courant is None:
718 for e in into_courant:
721 if liste_courante is not None and e in liste_courante:
723 liste_choix.append(e)
727 class LongStr(ListVal):
730 Validateur operationnel
731 Verification de la longueur d une chaine
734 def __init__(self, low, high):
735 ListVal.__init__(self, low=low, high=high)
741 return (tr("longueur de la chaine entre %s et %s") %( self.low, self.high))
743 def info_erreur_item(self):
744 return tr("Longueur de la chaine incorrecte")
746 def convert(self, valeur):
751 def verif_item(self, valeur):
758 def default(self, valeur, low, high):
759 if not is_str(valeur):
760 raise ValError ("%s n'est pas une chaine" % repr(valeur))
761 if valeur[0] == "'" and valeur[-1] == "'":
764 if len(valeur) < low or len(valeur) > high:
766 "%s n'est pas de la bonne longueur" % repr(valeur))
770 class OnlyStr(ListVal):
773 Validateur operationnel
774 Valide que c'est une chaine
778 ListVal.__init__(self)
782 return tr("regarde si c'est une chaine")
784 def info_erreur_item(self):
785 return tr("Ce n'est pas une chaine")
787 def convert(self, valeur):
792 def verif_item(self, valeur):
799 def default(self, valeur):
800 if not is_str(valeur):
801 raise ValError (tr("%s n'est pas une chaine") % repr(valeur))
805 class OrdList(ListVal):
808 Validateur operationnel
809 Verification qu'une liste est croissante ou decroissante
812 def __init__(self, ord):
813 ListVal.__init__(self, ord=ord)
818 return ("liste %s" % self.ord)
820 def info_erreur_liste(self):
821 return (tr("La liste doit etre en ordre %s") % self.ord)
823 def convert(self, valeur):
830 def default(self, valeur, ord):
831 if self.ord == 'croissant':
832 if self.val is not None and valeur < self.val:
834 (tr("%s n'est pas par valeurs croissantes") % repr(self.liste)))
835 elif self.ord == 'decroissant':
836 if self.val is not None and valeur > self.val:
838 (tr("%s n'est pas par valeurs decroissantes") % repr(self.liste)))
842 def verif_item(self, valeur):
845 def get_into(self, liste_courante=None, into_courant=None):
847 Methode get_into spécifique pour validateur OrdList, on retourne
848 une liste de choix qui ne contient aucune valeur de into_courant
849 dont la valeur est inférieure à la dernière valeur de
850 liste_courante, si elle est différente de None.
852 if into_courant is None:
854 elif not liste_courante:
858 last_val = liste_choix[-1]
859 for e in into_courant:
860 if self.ord == 'croissant' and e <= last_val:
862 if self.ord == 'decroissant' and e >= last_val:
864 liste_choix.append(e)
871 Validateur operationnel
872 Cette classe est un validateur qui controle une liste de validateurs
873 Elle verifie qu'au moins un des validateurs de la liste valide la valeur
876 def __init__(self, validators=()):
877 if not is_sequence(validators):
878 validators = (validators,)
880 for validator in validators:
881 if type(validator) == types.FunctionType:
882 self.validators.append(FunctionVal(validator))
884 self.validators.append(validator)
888 return "\n ou ".join([v.info() for v in self.validators])
890 def convert(self, valeur):
891 for validator in self.validators:
893 return validator.convert(valeur)
896 raise ValError(tr("%s n'est pas du bon type")% repr(valeur))
898 def info_erreur_item(self):
900 for v in self.validators:
901 err = v.info_erreur_item()
904 chaine = " \n ou ".join(l)
907 def info_erreur_liste(self):
909 for v in self.validators:
910 err = v.info_erreur_liste()
913 chaine = " \n ou ".join(l)
918 Si plusieurs validateurs sont reliés par un OU
919 il suffit qu'un seul des validateurs attende une liste
920 pour qu'on considère que leur union attend une liste.
922 for validator in self.validators:
923 v = validator.is_list()
928 def verif(self, valeur):
929 for validator in self.validators:
930 v = validator.verif(valeur)
935 def verif_item(self, valeur):
936 for validator in self.validators:
937 v = validator.verif_item(valeur)
942 def verif_cata(self):
944 for validator in self.validators:
945 v = validator.verif_cata()
947 infos.append(validator.cata_info)
949 self.cata_info = "\n".join(infos)
956 Dans le cas ou plusieurs validateurs sont reliés par un OU
957 il faut que tous les validateurs proposent un choix pour
958 qu'on considère que leur union propose un choix.
959 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
960 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
962 for validator in self.validators:
963 v = validator.has_into()
968 def get_into(self, liste_courante=None, into_courant=None):
970 Dans le cas ou plusieurs validateurs sont reliés par un OU
971 tous les validateurs doivent proposer un choix pour
972 qu'on considère que leur union propose un choix. Tous les choix
973 proposés par les validateurs sont réunis (opérateur d'union).
974 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
975 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
979 for validator in self.validators:
980 v_into = validator.get_into(liste_courante, into_courant)
983 validator_into.extend(v_into)
984 return validator_into
986 def valide_liste_partielle(self, liste_courante=None):
988 Méthode de validation de liste partielle pour le validateur Or.
989 Si un des validateurs gérés par le validateur Or considère la
990 liste comme valide, le validateur Or la considère comme valide.
992 for validator in self.validators:
993 v = validator.valide_liste_partielle(liste_courante)
1002 Validateur operationnel
1003 Cette classe est un validateur qui controle une liste de validateurs
1004 Elle verifie que tous les validateurs de la liste valident la valeur
1007 def __init__(self, validators=()):
1008 if not is_sequence(validators):
1009 validators = (validators,)
1010 self.validators = []
1011 for validator in validators:
1012 if type(validator) == types.FunctionType:
1013 self.validators.append(FunctionVal(validator))
1015 self.validators.append(validator)
1016 if hasattr(validator, 'fonctions'):
1017 for fonction in validator.fonctions:
1018 f = getattr(validator, fonction)
1019 setattr(self, fonction, f)
1023 return "\n et ".join([v.info() for v in self.validators])
1025 def convert(self, valeur):
1026 for validator in self.validators:
1027 valeur = validator.convert(valeur)
1030 def info_erreur_item(self):
1033 for v in self.validators:
1034 if v.info_erreur_item() != " ":
1036 chaine = v.info_erreur_item()
1039 chaine = chaine + " \n et " + v.info_erreur_item()
1042 def info_erreur_liste(self):
1045 for v in self.validators:
1046 if v.info_erreur_liste() != " ":
1048 chaine = v.info_erreur_liste()
1051 chaine = chaine + " \n et " + v.info_erreur_liste()
1054 def verif(self, valeur):
1055 for validator in self.validators:
1056 v = validator.verif(valeur)
1058 self.local_info = validator.info()
1062 def verif_item(self, valeur):
1063 for validator in self.validators:
1064 v = validator.verif_item(valeur)
1066 # L'info n'est probablement pas la meme que pour verif ???
1067 self.local_info = validator.info()
1071 def verif_cata(self):
1073 for validator in self.validators:
1074 v = validator.verif_cata()
1076 infos.append(validator.cata_info)
1078 self.cata_info = "\n".join(infos)
1083 def valide_liste_partielle(self, liste_courante=None):
1085 Méthode de validation de liste partielle pour le validateur And.
1086 Tous les validateurs gérés par le validateur And doivent considérer
1087 la liste comme valide, pour que le validateur And la considère
1090 for validator in self.validators:
1091 v = validator.valide_liste_partielle(liste_courante)
1098 Si plusieurs validateurs sont reliés par un ET
1099 il faut que tous les validateurs attendent une liste
1100 pour qu'on considère que leur intersection attende une liste.
1101 Exemple Range(2,5) ET Card(1) n'attend pas une liste
1102 Range(2,5) ET Pair attend une liste
1104 for validator in self.validators:
1105 v = validator.is_list()
1112 Dans le cas ou plusieurs validateurs sont reliés par un ET
1113 il suffit qu'un seul validateur propose un choix pour
1114 qu'on considère que leur intersection propose un choix.
1115 Exemple : Enum(1,2,3) ET entier pair, propose un choix
1116 En revanche, entier pair ET superieur à 10 ne propose pas de choix
1118 for validator in self.validators:
1119 v = validator.has_into()
1124 def get_into(self, liste_courante=None, into_courant=None):
1126 Dans le cas ou plusieurs validateurs sont reliés par un ET
1127 il suffit qu'un seul validateur propose un choix pour
1128 qu'on considère que leur intersection propose un choix. Tous les
1129 choix proposés par les validateurs sont croisés (opérateur
1131 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
1132 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
1134 for validator in self.validators:
1135 into_courant = validator.get_into(liste_courante, into_courant)
1136 if into_courant in ([], None):
1141 def do_liste(validators):
1143 Convertit une arborescence de validateurs en OrVal ou AndVal
1144 validators est une liste de validateurs ou de listes ou de tuples
1147 for validator in validators:
1148 if type(validator) == types.FunctionType:
1149 valids.append(FunctionVal(validator))
1150 elif type(validator) is tuple:
1151 valids.append(OrVal(do_liste(validator)))
1152 elif type(validator) is list:
1153 valids.append(AndVal(do_liste(validator)))
1155 valids.append(validator)
1159 def validatorFactory(validator):
1160 if type(validator) == types.FunctionType:
1161 return FunctionVal(validator)
1162 elif type(validator) is tuple:
1163 return OrVal(do_liste(validator))
1164 elif type(validator) is list:
1165 return AndVal(do_liste(validator))
1169 # Ci-dessous : exemples de validateur (peu testés)
1172 class RangeVal(ListVal):
1175 Exemple de classe validateur : verification qu'une valeur
1176 est dans un intervalle.
1177 Pour une liste on verifie que tous les elements sont
1179 Susceptible de remplacer les attributs "vale_min" "vale_max"
1183 def __init__(self, low, high):
1186 self.cata_info = (tr("%s doit etre inferieur a %s") % (low, high))
1189 return (tr("valeur dans l'intervalle %s , %s") %( self.low, self.high))
1191 def convert_item(self, valeur):
1192 if valeur > self.low and valeur < self.high:
1194 raise ValError(tr("%s devrait etre comprise entre %s et %s") % (valeur, self.low, self.high))
1196 def verif_item(self, valeur):
1197 return valeur > self.low and valeur < self.high
1199 def info_erreur_item(self):
1200 return (tr("la valeur %s doit etre comprise entre %s et %s") % (valeur, self.low, self.high))
1203 def verif_cata(self):
1204 if self.low > self.high:
1209 class CardVal(Valid):
1212 Exemple de classe validateur : verification qu'une liste est
1213 d'une longueur superieur a un minimum (min) et inferieure
1215 Susceptible de remplacer les attributs "min" "max" dans les
1219 def __init__(self, min=float('-inf'), max=float('inf')):
1222 self.cata_info = (tr("%s doit etre inferieur a %s") %(min, max))
1225 return (tr("longueur de liste comprise entre %s et %s") %(self.min, self.max))
1227 def info_erreur_liste(self):
1228 return (tr("Le cardinal de la liste doit etre compris entre %s et %s") % (self.min, self.max))
1231 return self.max == '**' or self.max > 1
1233 def get_into(self, liste_courante=None, into_courant=None):
1234 if into_courant is None:
1236 elif liste_courante is None:
1238 elif self.max == '**':
1240 elif len(liste_courante) < self.max:
1245 def convert(self, valeur):
1246 if is_sequence(valeur):
1248 elif valeur is None:
1252 if self.max != '**' and l > self.max:
1254 tr("%s devrait etre de longueur inferieure a %s") % (valeur, self.max))
1255 if self.min != '**' and l < self.min:
1257 tr("%s devrait etre de longueur superieure a %s") % (valeur, self.min))
1260 def verif_item(self, valeur):
1263 def verif(self, valeur):
1264 if is_sequence(valeur):
1265 if self.max != '**' and len(valeur) > self.max:
1267 if self.min != '**' and len(valeur) < self.min:
1271 if self.max != '**' and 1 > self.max:
1273 if self.min != '**' and 1 < self.min:
1277 def verif_cata(self):
1278 if self.min != '**' and self.max != '**' and self.min > self.max:
1282 def valide_liste_partielle(self, liste_courante=None):
1284 if liste_courante != None:
1285 if len(liste_courante) > self.max:
1290 class PairVal(ListVal):
1293 Exemple de classe validateur : verification qu'une valeur
1295 Pour une liste on verifie que tous les elements sont
1300 ListVal.__init__(self)
1304 return _(u"valeur paire")
1306 def info_erreur_item(self):
1307 return tr("La valeur saisie doit etre paire")
1309 def convert(self, valeur):
1314 tr("%s contient des valeurs non paires") % repr(valeur))
1317 def default(self, valeur):
1320 def verif_item(self, valeur):
1321 if type(valeur) not in six.integer_types:
1323 return valeur % 2 == 0
1325 def verif(self, valeur):
1326 if is_sequence(valeur):
1337 class EnumVal(ListVal):
1340 Exemple de classe validateur : verification qu'une valeur
1341 est prise dans une liste de valeurs.
1342 Susceptible de remplacer l attribut "into" dans les catalogues
1345 def __init__(self, into=()):
1346 if not is_sequence(into):
1352 return ("valeur dans %s" % self.into)
1354 def convert_item(self, valeur):
1355 if valeur in self.into:
1358 tr("%s contient des valeurs hors des choix possibles: %s ") % (valeur, self.into))
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 tr("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 (tr("valeur %s pour la somme des cles A et B ") % self.somme)
1417 def verif(self, valeur):
1418 if is_sequence(valeur):
1424 if val["A"] + val["B"] != self.somme:
1428 if not "A" in valeur:
1430 if not "B" in valeur:
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 info_erreur_item(self):
1451 return self.function.info
1453 def verif(self, valeur):
1454 return self.function(valeur)
1456 def verif_item(self, valeur):
1457 return self.function(valeur)
1459 def convert(self, valeur):
1462 # MC ca ne devrait plus servir !
1463 CoercableFuncs = {int: int,
1470 class TypeVal(ListVal):
1473 Exemple de validateur
1474 Cette classe est un validateur qui controle qu'une valeur
1475 est bien du type Python attendu.
1476 Pour une liste on verifie que tous les elements sont du bon type.
1477 Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1478 alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1481 def __init__(self, aType):
1482 # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1483 # type(1) == int;type(0.2)==float;etc.
1484 if type(aType) != type:
1488 self.coerce = CoercableFuncs[aType]
1490 self.coerce = self.identity
1493 return (tr("valeur de %s") % self.aType)
1495 def identity(self, value):
1496 if type(value) == self.aType:
1500 def convert_item(self, valeur):
1501 return self.coerce(valeur)
1503 def verif_item(self, valeur):
1511 class InstanceVal(ListVal):
1514 Exemple de validateur
1515 Cette classe est un validateur qui controle qu'une valeur est
1516 bien une instance (au sens Python) d'une classe
1517 Pour une liste on verifie chaque element de la liste
1520 def __init__(self, aClass):
1521 # Si aClass est une classe on la memorise dans self.aClass
1522 # sinon c'est une instance dont on memorise la classe
1523 if type(aClass) == types.InstanceType:
1524 # instance ancienne mode
1525 aClass = aClass.__class__
1526 elif type(aClass) == type:
1527 # classe ancienne mode
1529 elif type(aClass) == type:
1530 # classe nouvelle mode
1532 elif isinstance(aClass, object):
1533 # instance nouvelle mode
1534 aClass = type(aClass)
1536 raise ValError(tr("type non supporté"))
1538 self.aClass = aClass
1541 return (tr("valeur d'instance de %s") % self.aClass.__name__)
1543 def verif_item(self, valeur):
1544 if not isinstance(valeur, self.aClass):
1549 class VerifTypeTuple(ListVal):
1551 def __init__(self, typeDesTuples):
1552 self.typeDesTuples = typeDesTuples
1553 Valid.__init__(self)
1557 return tr(": verifie les types dans un tuple")
1559 def info_erreur_liste(self):
1560 return tr("Les types entres ne sont pas permis")
1562 def default(self, valeur):
1568 def convert_item(self, valeur):
1569 if len(valeur) != len(self.typeDesTuples):
1571 tr("%s devrait etre de type %s ") %( valeur, self.typeDesTuples))
1572 for i in range(len(valeur)):
1573 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1576 tr("%s devrait etre de type %s ") % (valeur, self.typeDesTuples))
1579 def verif_item(self, valeur):
1581 if len(valeur) != len(self.typeDesTuples):
1583 for i in range(len(valeur)):
1584 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1591 def verifType(self, valeur, type_permis):
1592 if type_permis == 'R':
1593 if type(valeur) in (int, float, int):
1595 elif type_permis == 'I':
1596 if type(valeur) in (int, int):
1598 elif type_permis == 'C':
1599 if self.is_complexe(valeur):
1601 elif type_permis == 'TXM':
1602 if type(valeur) == bytes:
1604 elif isinstance(valeur, type_permis):
1608 def verif(self, valeur):
1609 if type(valeur) in (list, tuple):
1610 liste = list(valeur)
1612 if self.verif_item(val) != 1:
1617 class VerifExiste(ListVal):
1620 fonctionne avec into
1621 Met une liste à jour selon les mot clefs existant
1622 exemple si into = ("A","B","C")
1623 si au niveau N du JDC les objets "A" et "C" existe
1624 alors la liste des into deviendra ( "A","C")
1626 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1627 niveauVerif est defini par rapport au Noeud :
1628 exemple niveauVerif = 1 : on verifie les freres
1629 niveauVerif = 2 : on verifie les oncles..
1632 def __init__(self, niveauVerif):
1633 ListVal.__init__(self)
1634 self.niveauVerif = niveauVerif
1636 self.listeDesFreres = ()
1637 self.fonctions = ('verifie_liste', 'set_MCSimp')
1642 def verifie_liste(self, liste):
1643 self.set_MCSimp(self.MCSimp)
1645 if not(item in self.listeDesFreres):
1649 def verif_item(self, valeur):
1650 self.set_MCSimp(self.MCSimp)
1651 if valeur in self.listeDesFreres:
1655 def set_MCSimp(self, MCSimp):
1656 self.MCSimp = MCSimp
1657 k = self.niveauVerif
1663 # on met la liste à jour
1664 parent.forceRecalcul = self.niveauVerif
1665 self.listeDesFreres = parent.liste_mc_presents()
1667 def convert_item(self, valeur):
1668 if valeur in self.listeDesFreres:
1671 tr("%s n'est pas dans %s") % (valeur, self.listeDesFreres))
1674 class RegExpVal(ListVal):
1677 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1680 errormsg = 'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1682 def __init__(self, pattern):
1683 self.pattern = pattern
1684 self.compiled_regexp = re.compile(pattern)
1687 return tr('Une chaîne correspondant au motif ') + str(self.pattern) + tr(" est attendue")
1689 def info_erreur_item(self):
1690 return tr('Une chaîne correspondant au motif ') + str(self.pattern) + tr(" est attendue")
1692 def verif_item(self, valeur):
1693 if self.compiled_regexp.match(valeur):
1696 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1698 def convert_item(self, valeur):
1699 if self.compiled_regexp.match(valeur):
1702 raise ValError(self.errormsg %
1703 {"value": valeur, "pattern": self.pattern})
1706 class FileExtVal(RegExpVal):
1709 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1712 def __init__(self, ext):
1714 self.errormsg = '"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1716 #PNPN Modif pour Adao
1717 RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
1721 return ('Un nom de fichier se terminant par ".%s" est attendu.' % self.ext)
1723 def info_erreur_item(self):
1724 return ('Un nom de fichier se terminant par ".%s" est attendu.' % self.ext)
1726 class CreeMotClef(object):
1727 def __init__(self,MotClef ):
1728 self.MotClef=MotClef
1731 def convert(self, lval):
1732 try : valeur=lval[0]
1733 except : return lval
1735 parent= self.MCSimp.parent
1736 if hasattr(parent, 'inhibeValidator') and parent.inhibeValidator: return lval
1739 if parent.get_child(self.MotClef) == None : longueur=0
1740 else : longueur=len(parent.get_child(self.MotClef))
1742 pos=parent.get_index_child(self.MCSimp.nom)+1
1743 while longueur < valeur :
1744 parent.inhibeValidator=1
1745 parent.addentite(self.MotClef,pos)
1747 parent.inhibeValidator=0
1748 longueur=len(parent.get_child(self.MotClef))
1750 if longueur > valeur :
1751 parent.inhibeValide=1
1752 parentObj=parent.get_child(self.MotClef)
1753 obj=parent.get_child(self.MotClef)[-1]
1754 parentObj.suppentite(obj)
1755 longueur=len(parent.get_child(self.MotClef))
1756 parent.inhibeValide=0
1760 return "Cree le bon nombre de Mot %s" % self.MotClef
1762 def verif_item(self, valeur):
1765 def set_MCSimp(self, MCSimp):
1766 #print "dans set_MCSimp"