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_permis == 'FichierOuRepertoire':
194 if os.path.isdir(obj) or os.path.isfile(obj): return obj
195 else: raise ValError( "%s n'est pas un fichier ou un repertoire valide" % repr(obj))
197 raise ValError( "%s n'est pas un fichier ou un repertoire valide" % repr(obj))
198 elif type(type_permis) == type or isinstance(type_permis, type):
200 if self.is_object_from(obj, type_permis):
202 except Exception as err:
204 elif type(type_permis) == types.InstanceType or isinstance(type_permis, object):
206 if type_permis.__convert__(obj):
208 except Exception as err:
211 print(("Type non encore gere %s" %type_permis))
213 tr("%s (de type %s) n'est pas d'un type autorise: %s %s") % (repr(obj), type(obj), typ, err))
215 def is_complexe(self, valeur):
216 """ Retourne 1 si valeur est un complexe, 0 sinon """
217 if is_number(valeur):
218 # Pour permettre l'utilisation de complexes Python (accepte les
221 elif type(valeur) != tuple:
222 # On n'autorise pas les listes pour les complexes
224 elif len(valeur) != 3:
227 # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
228 # valeur suivie de 2 reels.
229 if valeur[0].strip() in ('RI', 'MP'):
231 v1 = reelProto.adapt(valeur[1]), reelProto.adapt(valeur[2])
238 def is_object_from(self, objet, classe):
240 Retourne 1 si objet est une instance de la classe classe, 0 sinon
242 convert = getattr(classe, '__convert__', None)
243 if convert is not None:
244 # classe verifie les valeurs
248 except ValueError as err:
252 # On accepte les instances de la classe et des classes derivees
253 return isinstance(objet, classe)
255 reelProto = TypeProtocol("reel", typ=('R',))
258 class CardProtocol(PProtocol):
260 """Verificateur de cardinalité """
261 # pas de registre par instance. Registre unique pour toutes les instances
264 def __init__(self, name, min=1, max=1):
265 PProtocol.__init__(self, name, min=min, max=max)
267 def default(self, obj, min, max):
269 if (length < min) or( length > max):
271 "Nombre d'arguments de %s incorrect (min = %s, max = %s)" % (repr(obj), min, max))
275 class IntoProtocol(PProtocol):
277 """Verificateur de choix possibles : liste discrète ou intervalle"""
278 # pas de registre par instance. Registre unique pour toutes les instances
281 def __init__(self, name, into=None, val_min=float('-inf'), val_max=float('inf')):
284 self, name, into=into, val_min=val_min, val_max=val_max)
285 self.val_min = val_min
286 self.val_max = val_max
288 def default(self, obj, into, val_min, val_max):
289 if type(into) ==types.FunctionType :
290 maListeDeValeur=into()
295 tr("La valeur : %s ne fait pas partie des choix possibles %s") % (repr(obj), into))
297 # on est dans le cas d'un ensemble continu de valeurs possibles
299 if is_float_or_int(obj):
304 if obj < val_min or obj > val_max:
306 tr("La valeur : %s est en dehors du domaine de validite [ %s , %s ]") %(repr(obj), self.val_min, self.val_max))
310 class MinStr(object):
311 # exemple de classe pour verificateur de type
312 # on utilise des instances de classe comme type (typ=MinStr(3,6), par
315 def __init__(self, min, max):
319 def __convert__(self, valeur):
320 if is_str(valeur) and self.min <= len(valeur) <= self.max: return valeur
322 "%s n'est pas une chaine de longueur comprise entre %s et %s" % (valeur, self.min, self.max))
325 return tr("TXM de longueur entre %s et %s" % (self.min, self.max))
328 class Valid(PProtocol):
331 Cette classe est la classe mere des validateurs Accas
332 Elle doit etre derivee
333 Elle presente la signature des methodes indispensables pour son bon
334 fonctionnement et dans certains cas leur comportement par défaut.
336 @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
341 def __init__(self, **args):
342 PProtocol.__init__(self, "valid", **args)
346 Cette methode retourne une chaine de caractères informative sur
347 la validation demandée par le validateur. Elle est utilisée
348 pour produire le compte-rendu de validité du mot clé associé.
350 return "valeur valide"
354 Cette methode retourne une chaine de caractère qui permet
355 de construire un message d'aide en ligne.
356 En général, le message retourné est le meme que celui retourné par la
361 def info_erreur_item(self):
363 Cette méthode permet d'avoir un message d'erreur pour un item
364 dans une liste dans le cas ou le validateur fait des vérifications
365 sur les items d'une liste. Si le validateur fait seulement des
366 vérifications sur la liste elle meme et non sur ses items, la méthode
367 doit retourner une chaine vide.
371 def info_erreur_liste(self):
373 Cette méthode a un comportement complémentaire de celui de
374 info_erreur_item. Elle retourne un message d'erreur lié uniquement
375 aux vérifications sur la liste elle meme et pas sur ses items.
376 Dans le cas où le validateur ne fait pas de vérification sur des
377 listes, elle retourne une chaine vide
381 def verif(self, valeur):
383 Cette methode sert a verifier si la valeur passee en argument est consideree
384 comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
385 (valide) sinon 0 (invalide).
387 @type valeur: tout type python
388 @param valeur: valeur du mot cle a valider
390 @return: indicateur de validite 1 (valide) ou 0 (invalide)
392 raise NotImplementedError("Must be implemented")
394 def verif_item(self, valeur):
396 La methode verif du validateur effectue une validation complete de
397 la valeur. valeur peut etre un scalaire ou une liste. Le validateur
398 doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
399 methode is_list doit retourner 1).
400 La methode valid_item sert pour effectuer des validations partielles
401 de liste. Elle doit uniquement verifier la validite d'un item de
402 liste mais pas les caracteristiques de la liste.
406 def valide_liste_partielle(self, liste_courante):
408 Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
409 ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
410 veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
412 En général un validateur effectue la meme validation pour les listes partielles et les
415 return self.verif(liste_courante)
417 def verif_cata(self):
419 Cette methode sert a realiser des verifications du validateur lui meme.
420 Elle est facultative et retourne 1 (valide) par defaut.
421 Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
422 parametres de definition ne sont pas corrects.
423 La raison de l'invalidite est stockee dans l'attribut cata_info.
426 @return: indicateur de validite 1 (valide) ou 0 (invalide)
432 Cette méthode retourne un entier qui indique si le validateur
433 permet les listes (valeur 1) ou ne les permet pas (valeur 0).
434 Par défaut, un validateur n'autorise que des scalaires.
440 Cette méthode retourne un entier qui indique si le validateur
441 propose une liste de choix (valeur 1) ou n'en propose pas.
442 Par défaut, un validateur n'en propose pas.
446 def get_into(self, liste_courante=None, into_courant=None):
448 Cette méthode retourne la liste de choix proposée par le validateur.
449 Si le validateur ne propose pas de liste de choix, la méthode
451 L'argument d'entrée liste_courante, s'il est différent de None, donne
452 la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
453 méthode get_into doit calculer la liste des choix en en tenant
454 compte. Par exemple, si le validateur n'autorise pas les répétitions,
455 la liste des choix retournée ne doit pas contenir les choix déjà
456 contenus dans liste_courante.
457 L'argument d'entrée into_courant, s'il est différent de None, donne
458 la liste des choix proposés par d'autres validateurs. Dans ce cas,
459 la méthode get_into doit calculer la liste des choix à retourner
460 en se limitant à cette liste initiale. Par exemple, si into_courant
461 vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
462 la méthode ne doit retourner que (3,).
464 La méthode get_into peut retourner une liste vide [], ce qui veut
465 dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
466 peut etre normale : l''utilisateur a utilisé tous les choix, ou
467 résulter d'une incohérence des validateurs :
468 choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
469 faire la différence entre ces deux situations.
474 class ListVal(Valid):
477 Cette classe sert de classe mère pour tous les validateurs qui acceptent
484 def get_into(self, liste_courante=None, into_courant=None):
486 Cette méthode get_into effectue un traitement général qui consiste
487 a filtrer la liste de choix into_courant, si elle existe, en ne
488 conservant que les valeurs valides (appel de la méthode valid).
490 if into_courant is None:
494 for e in into_courant:
496 liste_choix.append(e)
499 def convert(self, valeur):
501 Méthode convert pour les validateurs de listes. Cette méthode
502 fait appel à la méthode convert_item sur chaque élément de la
505 if is_sequence(valeur):
507 self.convert_item(val)
510 return self.convert_item(valeur)
512 def verif(self, valeur):
514 Méthode verif pour les validateurs de listes. Cette méthode
515 fait appel à la méthode verif_item sur chaque élément de la
516 liste. Si valeur est un paramètre, on utilise sa valeur effective
519 if is_sequence(valeur):
521 if not self.verif_item(val):
525 return self.verif_item(valeur)
528 class Compulsory(ListVal):
530 Validateur operationnel
531 Verification de la présence obligatoire d'un élément dans une liste
535 def __init__(self, elem=()):
536 if not is_sequence(elem):
538 Valid.__init__(self, elem=elem)
543 return (tr(u"valeur %s obligatoire") % self.elem)
545 def default(self, valeur, elem):
548 def verif_item(self, valeur):
551 def convert(self, valeur):
552 elem = list(self.elem)
559 tr("%s ne contient pas les elements obligatoires : %s ") % (valeur, elem))
565 def verif(self, valeur):
566 if not is_sequence(valeur):
570 for val in self.elem:
575 def info_erreur_item(self):
576 return tr("La valeur n'est pas dans la liste des choix possibles")
579 class Together(ListVal):
581 Validateur operationnel
582 si un des éléments est présent les autres doivent aussi l'être
586 def __init__(self, elem=()):
587 if not is_sequence(elem):
589 Valid.__init__(self, elem=elem)
594 return (tr("%s present ensemble") % self.elem)
596 def default(self, valeur, elem):
599 def verif_item(self, valeur):
602 def convert(self, valeur):
603 elem = list(self.elem)
606 if v in elem: elem.remove(v)
607 if ( len(elem) == 0 ): return valeur
608 if len(elem) != len(list(self.elem)) :
609 raise ValError(tr("%s ne contient pas les elements devant etre presents ensemble: %s ") %( valeur, elem))
615 def verif(self, valeur):
616 if not is_sequence(valeur):
621 for val in self.elem:
622 if val in liste: compte += 1
623 if ( compte == 0 ): return 1
624 if ( compte != len( list(self.elem) ) ): return 0
627 def info_erreur_item(self):
628 return tr("La valeur n'est pas dans la liste des choix possibles")
631 class Absent(ListVal):
633 Validateur operationnel
634 si un des éléments est présent non valide
638 def __init__(self, elem=()):
639 if not is_sequence(elem):
641 Valid.__init__(self, elem=elem)
646 return (tr("%s absent") % self.elem)
648 def default(self, valeur, elem):
651 def verif_item(self, valeur):
654 def convert(self, valeur):
655 elem = list(self.elem)
659 raise ValError(tr("%s n'est pas autorise : %s ")% (v, elem))
665 def verif(self, valeur):
666 if not is_sequence(valeur):
670 for val in self.elem:
671 if val in liste: return 0
674 def info_erreur_item(self):
675 return tr("La valeur n'est pas dans la liste des choix possibles")
678 class NoRepeat(ListVal):
680 Validateur operationnel
681 Verification d'absence de doublons dans la liste.
688 return tr("Pas de doublon dans la liste")
690 def info_erreur_liste(self):
691 return tr("Les doublons ne sont pas permis")
693 def default(self, valeur):
694 if valeur in self.liste:
695 raise ValError( tr("%s est un doublon") % valeur)
698 def convert(self, valeur):
705 def verif_item(self, valeur):
708 def verif(self, valeur):
709 if is_sequence(valeur):
712 if liste.count(val) != 1:
718 def get_into(self, liste_courante=None, into_courant=None):
720 Methode get_into spécifique pour validateur NoRepeat, on retourne
721 une liste de choix qui ne contient aucune valeur de into_courant
722 déjà contenue dans liste_courante
724 if into_courant is None:
728 for e in into_courant:
731 if liste_courante is not None and e in liste_courante:
733 liste_choix.append(e)
737 class LongStr(ListVal):
740 Validateur operationnel
741 Verification de la longueur d une chaine
744 def __init__(self, low, high):
745 ListVal.__init__(self, low=low, high=high)
751 return (tr("longueur de la chaine entre %s et %s") %( self.low, self.high))
753 def info_erreur_item(self):
754 return tr("Longueur de la chaine incorrecte")
756 def convert(self, valeur):
761 def verif_item(self, valeur):
768 def default(self, valeur, low, high):
769 if not is_str(valeur):
770 raise ValError ("%s n'est pas une chaine" % repr(valeur))
771 if valeur[0] == "'" and valeur[-1] == "'":
774 if len(valeur) < low or len(valeur) > high:
776 "%s n'est pas de la bonne longueur" % repr(valeur))
780 class OnlyStr(ListVal):
783 Validateur operationnel
784 Valide que c'est une chaine
788 ListVal.__init__(self)
792 return tr("regarde si c'est une chaine")
794 def info_erreur_item(self):
795 return tr("Ce n'est pas une chaine")
797 def convert(self, valeur):
802 def verif_item(self, valeur):
809 def default(self, valeur):
810 if not is_str(valeur):
811 raise ValError (tr("%s n'est pas une chaine") % repr(valeur))
815 class OrdList(ListVal):
818 Validateur operationnel
819 Verification qu'une liste est croissante ou decroissante
822 def __init__(self, ord):
823 ListVal.__init__(self, ord=ord)
828 return ("liste %s" % self.ord)
830 def info_erreur_liste(self):
831 return (tr("La liste doit etre en ordre %s") % self.ord)
833 def convert(self, valeur):
840 def default(self, valeur, ord):
841 if self.ord == 'croissant':
842 if self.val is not None and valeur < self.val:
844 (tr("%s n'est pas par valeurs croissantes") % repr(self.liste)))
845 elif self.ord == 'decroissant':
846 if self.val is not None and valeur > self.val:
848 (tr("%s n'est pas par valeurs decroissantes") % repr(self.liste)))
852 def verif_item(self, valeur):
855 def get_into(self, liste_courante=None, into_courant=None):
857 Methode get_into spécifique pour validateur OrdList, on retourne
858 une liste de choix qui ne contient aucune valeur de into_courant
859 dont la valeur est inférieure à la dernière valeur de
860 liste_courante, si elle est différente de None.
862 if into_courant is None:
864 elif not liste_courante:
868 last_val = liste_choix[-1]
869 for e in into_courant:
870 if self.ord == 'croissant' and e <= last_val:
872 if self.ord == 'decroissant' and e >= last_val:
874 liste_choix.append(e)
881 Validateur operationnel
882 Cette classe est un validateur qui controle une liste de validateurs
883 Elle verifie qu'au moins un des validateurs de la liste valide la valeur
886 def __init__(self, validators=()):
887 if not is_sequence(validators):
888 validators = (validators,)
890 for validator in validators:
891 if type(validator) == types.FunctionType:
892 self.validators.append(FunctionVal(validator))
894 self.validators.append(validator)
898 return "\n ou ".join([v.info() for v in self.validators])
900 def convert(self, valeur):
901 for validator in self.validators:
903 return validator.convert(valeur)
906 raise ValError(tr("%s n'est pas du bon type")% repr(valeur))
908 def info_erreur_item(self):
910 for v in self.validators:
911 err = v.info_erreur_item()
914 chaine = " \n ou ".join(l)
917 def info_erreur_liste(self):
919 for v in self.validators:
920 err = v.info_erreur_liste()
923 chaine = " \n ou ".join(l)
928 Si plusieurs validateurs sont reliés par un OU
929 il suffit qu'un seul des validateurs attende une liste
930 pour qu'on considère que leur union attend une liste.
932 for validator in self.validators:
933 v = validator.is_list()
938 def verif(self, valeur):
939 for validator in self.validators:
940 v = validator.verif(valeur)
945 def verif_item(self, valeur):
946 for validator in self.validators:
947 v = validator.verif_item(valeur)
952 def verif_cata(self):
954 for validator in self.validators:
955 v = validator.verif_cata()
957 infos.append(validator.cata_info)
959 self.cata_info = "\n".join(infos)
966 Dans le cas ou plusieurs validateurs sont reliés par un OU
967 il faut que tous les validateurs proposent un choix pour
968 qu'on considère que leur union propose un choix.
969 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
970 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
972 for validator in self.validators:
973 v = validator.has_into()
978 def get_into(self, liste_courante=None, into_courant=None):
980 Dans le cas ou plusieurs validateurs sont reliés par un OU
981 tous les validateurs doivent proposer un choix pour
982 qu'on considère que leur union propose un choix. Tous les choix
983 proposés par les validateurs sont réunis (opérateur d'union).
984 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
985 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
989 for validator in self.validators:
990 v_into = validator.get_into(liste_courante, into_courant)
993 validator_into.extend(v_into)
994 return validator_into
996 def valide_liste_partielle(self, liste_courante=None):
998 Méthode de validation de liste partielle pour le validateur Or.
999 Si un des validateurs gérés par le validateur Or considère la
1000 liste comme valide, le validateur Or la considère comme valide.
1002 for validator in self.validators:
1003 v = validator.valide_liste_partielle(liste_courante)
1009 class AndVal(Valid):
1012 Validateur operationnel
1013 Cette classe est un validateur qui controle une liste de validateurs
1014 Elle verifie que tous les validateurs de la liste valident la valeur
1017 def __init__(self, validators=()):
1018 if not is_sequence(validators):
1019 validators = (validators,)
1020 self.validators = []
1021 for validator in validators:
1022 if type(validator) == types.FunctionType:
1023 self.validators.append(FunctionVal(validator))
1025 self.validators.append(validator)
1026 if hasattr(validator, 'fonctions'):
1027 for fonction in validator.fonctions:
1028 f = getattr(validator, fonction)
1029 setattr(self, fonction, f)
1033 return "\n et ".join([v.info() for v in self.validators])
1035 def convert(self, valeur):
1036 for validator in self.validators:
1037 valeur = validator.convert(valeur)
1040 def info_erreur_item(self):
1043 for v in self.validators:
1044 if v.info_erreur_item() != " ":
1046 chaine = v.info_erreur_item()
1049 chaine = chaine + " \n et " + v.info_erreur_item()
1052 def info_erreur_liste(self):
1055 for v in self.validators:
1056 if v.info_erreur_liste() != " ":
1058 chaine = v.info_erreur_liste()
1061 chaine = chaine + " \n et " + v.info_erreur_liste()
1064 def verif(self, valeur):
1065 for validator in self.validators:
1066 v = validator.verif(valeur)
1068 self.local_info = validator.info()
1072 def verif_item(self, valeur):
1073 for validator in self.validators:
1074 v = validator.verif_item(valeur)
1076 # L'info n'est probablement pas la meme que pour verif ???
1077 self.local_info = validator.info()
1081 def verif_cata(self):
1083 for validator in self.validators:
1084 v = validator.verif_cata()
1086 infos.append(validator.cata_info)
1088 self.cata_info = "\n".join(infos)
1093 def valide_liste_partielle(self, liste_courante=None):
1095 Méthode de validation de liste partielle pour le validateur And.
1096 Tous les validateurs gérés par le validateur And doivent considérer
1097 la liste comme valide, pour que le validateur And la considère
1100 for validator in self.validators:
1101 v = validator.valide_liste_partielle(liste_courante)
1108 Si plusieurs validateurs sont reliés par un ET
1109 il faut que tous les validateurs attendent une liste
1110 pour qu'on considère que leur intersection attende une liste.
1111 Exemple Range(2,5) ET Card(1) n'attend pas une liste
1112 Range(2,5) ET Pair attend une liste
1114 for validator in self.validators:
1115 v = validator.is_list()
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.
1125 Exemple : Enum(1,2,3) ET entier pair, propose un choix
1126 En revanche, entier pair ET superieur à 10 ne propose pas de choix
1128 for validator in self.validators:
1129 v = validator.has_into()
1134 def get_into(self, liste_courante=None, into_courant=None):
1136 Dans le cas ou plusieurs validateurs sont reliés par un ET
1137 il suffit qu'un seul validateur propose un choix pour
1138 qu'on considère que leur intersection propose un choix. Tous les
1139 choix proposés par les validateurs sont croisés (opérateur
1141 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
1142 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
1144 for validator in self.validators:
1145 into_courant = validator.get_into(liste_courante, into_courant)
1146 if into_courant in ([], None):
1151 def do_liste(validators):
1153 Convertit une arborescence de validateurs en OrVal ou AndVal
1154 validators est une liste de validateurs ou de listes ou de tuples
1157 for validator in validators:
1158 if type(validator) == types.FunctionType:
1159 valids.append(FunctionVal(validator))
1160 elif type(validator) is tuple:
1161 valids.append(OrVal(do_liste(validator)))
1162 elif type(validator) is list:
1163 valids.append(AndVal(do_liste(validator)))
1165 valids.append(validator)
1169 def validatorFactory(validator):
1170 if type(validator) == types.FunctionType:
1171 return FunctionVal(validator)
1172 elif type(validator) is tuple:
1173 return OrVal(do_liste(validator))
1174 elif type(validator) is list:
1175 return AndVal(do_liste(validator))
1179 # Ci-dessous : exemples de validateur (peu testés)
1182 class RangeVal(ListVal):
1185 Exemple de classe validateur : verification qu'une valeur
1186 est dans un intervalle.
1187 Pour une liste on verifie que tous les elements sont
1189 Susceptible de remplacer les attributs "vale_min" "vale_max"
1193 def __init__(self, low, high):
1196 self.cata_info = (tr("%s doit etre inferieur a %s") % (low, high))
1199 return (tr("valeur dans l'intervalle %s , %s") %( self.low, self.high))
1201 def convert_item(self, valeur):
1202 if valeur > self.low and valeur < self.high:
1204 raise ValError(tr("%s devrait etre comprise entre %s et %s") % (valeur, self.low, self.high))
1206 def verif_item(self, valeur):
1207 return valeur > self.low and valeur < self.high
1209 def info_erreur_item(self):
1210 return (tr("la valeur %s doit etre comprise entre %s et %s") % (valeur, self.low, self.high))
1213 def verif_cata(self):
1214 if self.low > self.high:
1219 class CardVal(Valid):
1222 Exemple de classe validateur : verification qu'une liste est
1223 d'une longueur superieur a un minimum (min) et inferieure
1225 Susceptible de remplacer les attributs "min" "max" dans les
1229 def __init__(self, min=float('-inf'), max=float('inf')):
1232 self.cata_info = (tr("%s doit etre inferieur a %s") %(min, max))
1235 return (tr("longueur de liste comprise entre %s et %s") %(self.min, self.max))
1237 def info_erreur_liste(self):
1238 return (tr("Le cardinal de la liste doit etre compris entre %s et %s") % (self.min, self.max))
1241 return self.max == '**' or self.max > 1
1243 def get_into(self, liste_courante=None, into_courant=None):
1244 if into_courant is None:
1246 elif liste_courante is None:
1248 elif self.max == '**':
1250 elif len(liste_courante) < self.max:
1255 def convert(self, valeur):
1256 if is_sequence(valeur):
1258 elif valeur is None:
1262 if self.max != '**' and l > self.max:
1264 tr("%s devrait etre de longueur inferieure a %s") % (valeur, self.max))
1265 if self.min != '**' and l < self.min:
1267 tr("%s devrait etre de longueur superieure a %s") % (valeur, self.min))
1270 def verif_item(self, valeur):
1273 def verif(self, valeur):
1274 if is_sequence(valeur):
1275 if self.max != '**' and len(valeur) > self.max:
1277 if self.min != '**' and len(valeur) < self.min:
1281 if self.max != '**' and 1 > self.max:
1283 if self.min != '**' and 1 < self.min:
1287 def verif_cata(self):
1288 if self.min != '**' and self.max != '**' and self.min > self.max:
1292 def valide_liste_partielle(self, liste_courante=None):
1294 if liste_courante != None:
1295 if len(liste_courante) > self.max:
1300 class PairVal(ListVal):
1303 Exemple de classe validateur : verification qu'une valeur
1305 Pour une liste on verifie que tous les elements sont
1310 ListVal.__init__(self)
1314 return _(u"valeur paire")
1316 def info_erreur_item(self):
1317 return tr("La valeur saisie doit etre paire")
1319 def convert(self, valeur):
1324 tr("%s contient des valeurs non paires") % repr(valeur))
1327 def default(self, valeur):
1330 def verif_item(self, valeur):
1331 if type(valeur) not in six.integer_types:
1333 return valeur % 2 == 0
1335 def verif(self, valeur):
1336 if is_sequence(valeur):
1347 class EnumVal(ListVal):
1350 Exemple de classe validateur : verification qu'une valeur
1351 est prise dans une liste de valeurs.
1352 Susceptible de remplacer l attribut "into" dans les catalogues
1355 def __init__(self, into=()):
1356 if not is_sequence(into):
1362 return ("valeur dans %s" % self.into)
1364 def convert_item(self, valeur):
1365 if valeur in self.into:
1368 tr("%s contient des valeurs hors des choix possibles: %s ") % (valeur, self.into))
1370 def verif_item(self, valeur):
1371 if valeur not in self.into:
1378 def get_into(self, liste_courante=None, into_courant=None):
1379 if into_courant is None:
1380 liste_choix = list(self.into)
1383 for e in into_courant:
1385 liste_choix.append(e)
1388 def info_erreur_item(self):
1389 return tr("La valeur n'est pas dans la liste des choix possibles")
1392 def ImpairVal(valeur):
1394 Exemple de validateur
1395 Cette fonction est un validateur. Elle verifie que la valeur passee
1396 est bien un nombre impair.
1398 if is_sequence(valeur):
1408 ImpairVal.info = "valeur impaire"
1414 Exemple de validateur
1415 Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1416 que la somme des cles A et B vaut une valeur donnee
1417 en parametre du validateur
1420 def __init__(self, somme=10):
1425 return (tr("valeur %s pour la somme des cles A et B ") % self.somme)
1427 def verif(self, valeur):
1428 if is_sequence(valeur):
1434 if val["A"] + val["B"] != self.somme:
1438 if not "A" in valeur:
1440 if not "B" in valeur:
1442 if valeur["A"] + valeur["B"] != self.somme:
1447 class FunctionVal(Valid):
1450 Exemple de validateur
1451 Cette classe est un validateur qui est initialise avec une fonction
1454 def __init__(self, function):
1455 self.function = function
1458 return self.function.info
1460 def info_erreur_item(self):
1461 return self.function.info
1463 def verif(self, valeur):
1464 return self.function(valeur)
1466 def verif_item(self, valeur):
1467 return self.function(valeur)
1469 def convert(self, valeur):
1472 # MC ca ne devrait plus servir !
1473 CoercableFuncs = {int: int,
1480 #class FunctionValObjet(FunctionVal):
1483 class TypeVal(ListVal):
1486 Exemple de validateur
1487 Cette classe est un validateur qui controle qu'une valeur
1488 est bien du type Python attendu.
1489 Pour une liste on verifie que tous les elements sont du bon type.
1490 Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1491 alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1494 def __init__(self, aType):
1495 # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1496 # type(1) == int;type(0.2)==float;etc.
1497 if type(aType) != type:
1501 self.coerce = CoercableFuncs[aType]
1503 self.coerce = self.identity
1506 return (tr("valeur de %s") % self.aType)
1508 def identity(self, value):
1509 if type(value) == self.aType:
1513 def convert_item(self, valeur):
1514 return self.coerce(valeur)
1516 def verif_item(self, valeur):
1524 class InstanceVal(ListVal):
1527 Exemple de validateur
1528 Cette classe est un validateur qui controle qu'une valeur est
1529 bien une instance (au sens Python) d'une classe
1530 Pour une liste on verifie chaque element de la liste
1533 def __init__(self, aClass):
1534 # Si aClass est une classe on la memorise dans self.aClass
1535 # sinon c'est une instance dont on memorise la classe
1536 if type(aClass) == types.InstanceType:
1537 # instance ancienne mode
1538 aClass = aClass.__class__
1539 elif type(aClass) == type:
1540 # classe ancienne mode
1542 elif type(aClass) == type:
1543 # classe nouvelle mode
1545 elif isinstance(aClass, object):
1546 # instance nouvelle mode
1547 aClass = type(aClass)
1549 raise ValError(tr("type non supporté"))
1551 self.aClass = aClass
1554 return (tr("valeur d'instance de %s") % self.aClass.__name__)
1556 def verif_item(self, valeur):
1557 if not isinstance(valeur, self.aClass):
1562 class VerifTypeTuple(ListVal):
1564 def __init__(self, typeDesTuples):
1565 self.typeDesTuples = typeDesTuples
1566 Valid.__init__(self)
1570 return tr(": verifie les types dans un tuple")
1572 def info_erreur_liste(self):
1573 return tr("Les types entres ne sont pas permis")
1575 def default(self, valeur):
1581 def convert_item(self, valeur):
1582 if len(valeur) != len(self.typeDesTuples):
1584 tr("%s devrait etre de type %s ") %( valeur, self.typeDesTuples))
1585 for i in range(len(valeur)):
1586 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1589 tr("%s devrait etre de type %s ") % (valeur, self.typeDesTuples))
1592 def verif_item(self, valeur):
1594 if len(valeur) != len(self.typeDesTuples):
1596 for i in range(len(valeur)):
1597 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1604 def verifType(self, valeur, type_permis):
1605 if type_permis == 'R':
1606 if type(valeur) in (int, float, int):
1608 elif type_permis == 'I':
1609 if type(valeur) in (int, int):
1611 elif type_permis == 'C':
1612 if self.is_complexe(valeur):
1614 elif type_permis == 'TXM':
1615 if type(valeur) == bytes:
1617 elif isinstance(valeur, type_permis):
1621 def verif(self, valeur):
1622 if type(valeur) in (list, tuple):
1623 liste = list(valeur)
1625 if self.verif_item(val) != 1:
1630 class VerifExiste(ListVal):
1633 fonctionne avec into
1634 Met une liste à jour selon les mot clefs existant
1635 exemple si into = ("A","B","C")
1636 si au niveau N du JDC les objets "A" et "C" existe
1637 alors la liste des into deviendra ( "A","C")
1639 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1640 niveauVerif est defini par rapport au Noeud :
1641 exemple niveauVerif = 1 : on verifie les freres
1642 niveauVerif = 2 : on verifie les oncles..
1645 def __init__(self, niveauVerif):
1646 ListVal.__init__(self)
1647 self.niveauVerif = niveauVerif
1649 self.listeDesFreres = ()
1650 self.fonctions = ('verifie_liste', 'set_MCSimp')
1655 def verifie_liste(self, liste):
1656 self.set_MCSimp(self.MCSimp)
1658 if not(item in self.listeDesFreres):
1662 def verif_item(self, valeur):
1663 self.set_MCSimp(self.MCSimp)
1664 if valeur in self.listeDesFreres:
1668 def set_MCSimp(self, MCSimp):
1669 self.MCSimp = MCSimp
1670 k = self.niveauVerif
1676 # on met la liste à jour
1677 parent.forceRecalcul = self.niveauVerif
1678 self.listeDesFreres = parent.liste_mc_presents()
1680 def convert_item(self, valeur):
1681 if valeur in self.listeDesFreres:
1684 tr("%s n'est pas dans %s") % (valeur, self.listeDesFreres))
1687 class RegExpVal(ListVal):
1690 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1693 errormsg = 'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1695 def __init__(self, pattern):
1696 self.pattern = pattern
1697 self.compiled_regexp = re.compile(pattern)
1700 return tr('Une chaîne correspondant au motif ') + str(self.pattern) + tr(" est attendue")
1702 def info_erreur_item(self):
1703 return tr('Une chaîne correspondant au motif ') + str(self.pattern) + tr(" est attendue")
1705 def verif_item(self, valeur):
1706 if self.compiled_regexp.match(valeur):
1709 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1711 def convert_item(self, valeur):
1712 if self.compiled_regexp.match(valeur):
1715 raise ValError(self.errormsg %
1716 {"value": valeur, "pattern": self.pattern})
1719 class FileExtVal(RegExpVal):
1722 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1725 def __init__(self, ext):
1727 self.errormsg = '"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1729 #PNPN Modif pour Adao
1730 RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
1734 return ('Un nom de fichier se terminant par ".%s" est attendu.' % self.ext)
1736 def info_erreur_item(self):
1737 return ('Un nom de fichier se terminant par ".%s" est attendu.' % self.ext)
1739 class CreeMotClef(object):
1740 def __init__(self,MotClef ):
1741 self.MotClef=MotClef
1744 def convert(self, lval):
1745 try : valeur=lval[0]
1746 except : return lval
1748 parent= self.MCSimp.parent
1749 if hasattr(parent, 'inhibeValidator') and parent.inhibeValidator: return lval
1752 if parent.get_child(self.MotClef) == None : longueur=0
1753 else : longueur=len(parent.get_child(self.MotClef))
1755 pos=parent.get_index_child(self.MCSimp.nom)+1
1756 while longueur < valeur :
1757 parent.inhibeValidator=1
1758 parent.addentite(self.MotClef,pos)
1760 parent.inhibeValidator=0
1761 longueur=len(parent.get_child(self.MotClef))
1763 if longueur > valeur :
1764 parent.inhibeValide=1
1765 parentObj=parent.get_child(self.MotClef)
1766 obj=parent.get_child(self.MotClef)[-1]
1767 parentObj.suppentite(obj)
1768 longueur=len(parent.get_child(self.MotClef))
1769 parent.inhibeValide=0
1773 return "Cree le bon nombre de Mot %s" % self.MotClef
1775 def verif_item(self, valeur):
1778 def set_MCSimp(self, MCSimp):
1779 #print "dans set_MCSimp"