2 # Copyright (C) 2007-2017 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 isInt, isFloat_or_int, isComplex, isNumber, isStr, isSequence
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 isFloat_or_int(obj):
155 elif type_permis == 'I':
158 elif type_permis == 'C':
159 if self.isComplexe(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.isObjectFrom(obj, type_permis):
202 except Exception as err:
204 elif 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 isComplexe(self, valeur):
216 """ Retourne 1 si valeur est un complexe, 0 sinon """
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 isObjectFrom(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 isFloat_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 isStr(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 infoErreurItem(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 infoErreurListe(self):
373 Cette méthode a un comportement complémentaire de celui de
374 infoErreurItem. 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 verifItem(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 isList 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 valideListePartielle(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)
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 getInto(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 getInto 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 getInto 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 getInto 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 getInto(self, liste_courante=None, into_courant=None):
486 Cette méthode getInto 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 convertItem sur chaque élément de la
505 if isSequence(valeur):
507 self.convertItem(val)
510 return self.convertItem(valeur)
512 def verif(self, valeur):
514 Méthode verif pour les validateurs de listes. Cette méthode
515 fait appel à la méthode verifItem sur chaque élément de la
516 liste. Si valeur est un paramètre, on utilise sa valeur effective
519 if isSequence(valeur):
521 if not self.verifItem(val):
525 return self.verifItem(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 isSequence(elem):
538 Valid.__init__(self, elem=elem)
543 return (tr(u"valeur %s obligatoire") % self.elem)
545 def default(self, valeur, elem):
548 def verifItem(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 isSequence(valeur):
570 for val in self.elem:
575 def infoErreurItem(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 isSequence(elem):
589 Valid.__init__(self, elem=elem)
594 return (tr("%s present ensemble") % self.elem)
596 def default(self, valeur, elem):
599 def verifItem(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 isSequence(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 infoErreurItem(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 isSequence(elem):
641 Valid.__init__(self, elem=elem)
646 return (tr("%s absent") % self.elem)
648 def default(self, valeur, elem):
651 def verifItem(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 isSequence(valeur):
670 for val in self.elem:
671 if val in liste: return 0
674 def infoErreurItem(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 infoErreurListe(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 verifItem(self, valeur):
708 def verif(self, valeur):
709 if isSequence(valeur):
712 if liste.count(val) != 1:
718 def getInto(self, liste_courante=None, into_courant=None):
720 Methode getInto 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 infoErreurItem(self):
754 return tr("Longueur de la chaine incorrecte")
756 def convert(self, valeur):
761 def verifItem(self, valeur):
768 def default(self, valeur, low, high):
769 if not isStr(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 infoErreurItem(self):
795 return tr("Ce n'est pas une chaine")
797 def convert(self, valeur):
802 def verifItem(self, valeur):
809 def default(self, valeur):
810 if not isStr(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 infoErreurListe(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 verifItem(self, valeur):
855 def getInto(self, liste_courante=None, into_courant=None):
857 Methode getInto 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 isSequence(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 infoErreurItem(self):
910 for v in self.validators:
911 err = v.infoErreurItem()
914 chaine = " \n ou ".join(l)
917 def infoErreurListe(self):
919 for v in self.validators:
920 err = v.infoErreurListe()
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.isList()
938 def verif(self, valeur):
939 for validator in self.validators:
940 v = validator.verif(valeur)
945 def verifItem(self, valeur):
946 for validator in self.validators:
947 v = validator.verifItem(valeur)
954 for validator in self.validators:
955 v = validator.verifCata()
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.hasInto()
978 def getInto(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.getInto(liste_courante, into_courant)
993 validator_into.extend(v_into)
994 return validator_into
996 def valideListePartielle(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.valideListePartielle(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 isSequence(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 infoErreurItem(self):
1043 for v in self.validators:
1044 if v.infoErreurItem() != " ":
1046 chaine = v.infoErreurItem()
1049 chaine = chaine + " \n et " + v.infoErreurItem()
1052 def infoErreurListe(self):
1055 for v in self.validators:
1056 if v.infoErreurListe() != " ":
1058 chaine = v.infoErreurListe()
1061 chaine = chaine + " \n et " + v.infoErreurListe()
1064 def verif(self, valeur):
1065 for validator in self.validators:
1066 v = validator.verif(valeur)
1068 self.local_info = validator.info()
1072 def verifItem(self, valeur):
1073 for validator in self.validators:
1074 v = validator.verifItem(valeur)
1076 # L'info n'est probablement pas la meme que pour verif ???
1077 self.local_info = validator.info()
1081 def verifCata(self):
1083 for validator in self.validators:
1084 v = validator.verifCata()
1086 infos.append(validator.cata_info)
1088 self.cata_info = "\n".join(infos)
1093 def valideListePartielle(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.valideListePartielle(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.isList()
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.hasInto()
1134 def getInto(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.getInto(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 convertItem(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 verifItem(self, valeur):
1207 return valeur > self.low and valeur < self.high
1209 def infoErreurItem(self):
1210 return (tr("la valeur %s doit etre comprise entre %s et %s") % (valeur, self.low, self.high))
1213 def verifCata(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 infoErreurListe(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 getInto(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 isSequence(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 verifItem(self, valeur):
1273 def verif(self, valeur):
1274 if isSequence(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 verifCata(self):
1288 if self.min != '**' and self.max != '**' and self.min > self.max:
1292 def valideListePartielle(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 infoErreurItem(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 verifItem(self, valeur):
1331 if type(valeur) not in six.integer_types:
1333 return valeur % 2 == 0
1335 def verif(self, valeur):
1336 if isSequence(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 isSequence(into):
1362 return ("valeur dans %s" % self.into)
1364 def convertItem(self, valeur):
1365 if valeur in self.into:
1368 tr("%s contient des valeurs hors des choix possibles: %s ") % (valeur, self.into))
1370 def verifItem(self, valeur):
1371 if valeur not in self.into:
1378 def getInto(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 infoErreurItem(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 isSequence(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 isSequence(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 infoErreurItem(self):
1461 return self.function.info
1463 def verif(self, valeur):
1464 return self.function(valeur)
1466 def verifItem(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 convertItem(self, valeur):
1514 return self.coerce(valeur)
1516 def verifItem(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 if type(aClass) == object :
1538 # instance ancienne mode
1539 aClass = aClass.__class__
1540 elif type(aClass) == type:
1541 # classe ancienne mode
1543 elif type(aClass) == type:
1544 # classe nouvelle mode
1546 elif isinstance(aClass, object):
1547 # instance nouvelle mode
1548 aClass = type(aClass)
1550 raise ValError(tr("type non supporté"))
1552 self.aClass = aClass
1555 return (tr("valeur d'instance de %s") % self.aClass.__name__)
1557 def verifItem(self, valeur):
1558 if not isinstance(valeur, self.aClass):
1563 class VerifTypeTuple(ListVal):
1565 def __init__(self, typeDesTuples):
1566 self.typeDesTuples = typeDesTuples
1567 Valid.__init__(self)
1571 return tr(": verifie les \ntypes dans un tuple")
1573 def infoErreurListe(self):
1574 return tr("Les types entres ne sont pas permis")
1576 def default(self, valeur):
1582 def convertItem(self, valeur):
1583 if len(valeur) != len(self.typeDesTuples):
1585 tr("%s devrait etre de type %s ") %( valeur, self.typeDesTuples))
1586 for i in range(len(valeur)):
1587 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1590 tr("%s devrait etre de type %s ") % (valeur, self.typeDesTuples))
1593 def verifItem(self, valeur):
1595 if len(valeur) != len(self.typeDesTuples):
1597 for i in range(len(valeur)):
1598 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1605 def verifType(self, valeur, type_permis):
1606 if type_permis == 'R':
1607 if type(valeur) in (int, float, int):
1609 elif type_permis == 'I':
1610 if type(valeur) in (int, int):
1612 elif type_permis == 'C':
1613 if self.isComplexe(valeur):
1615 elif type_permis == 'TXM':
1616 if type(valeur) == bytes or type(valeur) == str:
1618 elif isinstance(valeur, type_permis):
1622 def verif(self, valeur):
1623 if type(valeur) in (list, tuple):
1624 liste = list(valeur)
1626 if self.verifItem(val) != 1:
1631 class VerifExiste(ListVal):
1634 fonctionne avec into
1635 Met une liste à jour selon les mot clefs existant
1636 exemple si into = ("A","B","C")
1637 si au niveau N du JDC les objets "A" et "C" existe
1638 alors la liste des into deviendra ( "A","C")
1640 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1641 niveauVerif est defini par rapport au Noeud :
1642 exemple niveauVerif = 1 : on verifie les freres
1643 niveauVerif = 2 : on verifie les oncles..
1646 def __init__(self, niveauVerif):
1647 ListVal.__init__(self)
1648 self.niveauVerif = niveauVerif
1650 self.listeDesFreres = ()
1651 self.fonctions = ('verifieListe', 'set_MCSimp')
1656 def verifieListe(self, liste):
1657 self.set_MCSimp(self.MCSimp)
1659 if not(item in self.listeDesFreres):
1663 def verifItem(self, valeur):
1664 self.set_MCSimp(self.MCSimp)
1665 if valeur in self.listeDesFreres:
1669 def set_MCSimp(self, MCSimp):
1670 self.MCSimp = MCSimp
1671 k = self.niveauVerif
1677 # on met la liste à jour
1678 parent.forceRecalcul = self.niveauVerif
1679 self.listeDesFreres = parent.listeMcPresents()
1681 def convertItem(self, valeur):
1682 if valeur in self.listeDesFreres:
1685 tr("%s n'est pas dans %s") % (valeur, self.listeDesFreres))
1688 class RegExpVal(ListVal):
1691 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1694 errormsg = 'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1696 def __init__(self, pattern):
1697 self.pattern = pattern
1698 self.compiled_regexp = re.compile(pattern)
1701 return tr('Une chaîne correspondant au motif ') + str(self.pattern) + tr(" est attendue")
1703 def infoErreurItem(self):
1704 return tr('Une chaîne correspondant au motif ') + str(self.pattern) + tr(" est attendue")
1706 def verifItem(self, valeur):
1707 if self.compiled_regexp.match(valeur):
1710 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1712 def convertItem(self, valeur):
1713 if self.compiled_regexp.match(valeur):
1716 raise ValError(self.errormsg %
1717 {"value": valeur, "pattern": self.pattern})
1720 class FileExtVal(RegExpVal):
1723 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1726 def __init__(self, ext):
1728 self.errormsg = '"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1730 #PNPN Modif pour Adao
1731 RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
1735 return ('Un nom de fichier se terminant par ".%s" est attendu.' % self.ext)
1737 def infoErreurItem(self):
1738 return ('Un nom de fichier se terminant par ".%s" est attendu.' % self.ext)
1740 class CreeMotClef(object):
1741 def __init__(self,MotClef ):
1742 self.MotClef=MotClef
1745 def convert(self, lval):
1746 try : valeur=lval[0]
1747 except : return lval
1749 parent= self.MCSimp.parent
1750 if hasattr(parent, 'inhibeValidator') and parent.inhibeValidator: return lval
1753 if parent.getChild(self.MotClef) == None : longueur=0
1754 else : longueur=len(parent.getChild(self.MotClef))
1756 pos=parent.getIndexChild(self.MCSimp.nom)+1
1757 while longueur < valeur :
1758 parent.inhibeValidator=1
1759 parent.addEntite(self.MotClef,pos)
1761 parent.inhibeValidator=0
1762 longueur=len(parent.getChild(self.MotClef))
1764 if longueur > valeur :
1765 parent.inhibeValide=1
1766 parentObj=parent.getChild(self.MotClef)
1767 obj=parent.getChild(self.MotClef)[-1]
1768 parentObj.suppEntite(obj)
1769 longueur=len(parent.getChild(self.MotClef))
1770 parent.inhibeValide=0
1774 return "Cree le bon nombre de Mot %s" % self.MotClef
1776 def verifItem(self, valeur):
1779 def set_MCSimp(self, MCSimp):
1780 #print "dans set_MCSimp"