2 # Copyright (C) 2007-2021 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 object
37 from .N_ASSD import ASSD
38 from .N_types import isInt, isFloat_or_int, isComplex, isNumber, isStr, isSequence
39 from Accas import A_TUPLE
40 from Extensions.i18n import tr
44 class ValError(Exception):
49 if hasattr(cls, "__mro__"):
52 for base in cls.__bases__:
53 mro.extend(cls_mro(base))
57 class Protocol(object):
59 def __init__(self, name):
64 def register(self, T, A):
65 print ('register Protocol',T,A)
69 # (a) verifier si l'objet peut s'adapter au protocole
70 adapt = getattr(obj, '__adapt__', None)
72 # on demande à l'objet obj de réaliser lui-meme l'adaptation
75 # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
77 for T in cls_mro(obj.__class__):
78 if T in self.registry:
79 return self.registry[T](obj, self, **self.args)
81 # (c) utiliser l'adapteur par defaut
82 return self.default(obj, **self.args)
84 def default(self, obj, **args):
85 raise TypeError("Can't adapt %s to %s" %
86 (obj.__class__.__name__, self.name))
89 class PProtocol(Protocol):
91 """Verificateur de protocole paramétré (classe de base)"""
92 # Protocole paramétré. Le registre est unique pour toutes les instances.
93 # La methode register est une methode de classe
96 def __init__(self, name, **args):
100 def register(cls, T, A):
102 register = classmethod(register)
105 class ListProtocol(Protocol):
107 """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
109 def default(self, obj):
110 if type(obj) is tuple:
111 if len(obj) > 0 and obj[0] in ('RI', 'MP'):
112 # il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
116 elif type(obj) is list:
119 # pas de valeur affecte. La cardinalite vaut 0
122 # il s'agit d'une chaine. La cardinalite vaut 1
126 # si l'objet supporte len, on a la cardinalite
133 listProto = ListProtocol("list")
136 class TypeProtocol(PProtocol):
138 """Verificateur de type parmi une liste de types possibles"""
139 # pas de registre par instance. Registre unique pour toutes les instances
143 def __init__(self, name, typ=None):
144 PProtocol.__init__(self, name, typ=typ)
147 def default(self, obj, typ):
149 for type_permis in typ:
150 if type_permis == 'createObject': continue
151 if type_permis == 'R':
152 if isFloat_or_int(obj):
154 elif type_permis == 'I':
157 elif type_permis == 'C':
158 if self.isComplexe(obj):
160 elif type_permis == 'TXM':
163 elif type_permis == 'shell':
166 elif type_permis == 'Fichier':
169 if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj):
172 raise ValError( "%s n'est pas un fichier valide" % repr(obj))
174 raise ValError( "%s n'est pas un fichier valide" % repr(obj))
176 elif type_permis == 'FichierNoAbs':
178 if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")):
181 raise ValError( "%s n'est pas un fichier valide" % repr(obj))
183 elif type_permis == 'Repertoire':
186 if os.path.isdir(obj): return obj
187 else: raise ValError( "%s n'est pas un repertoire valide" % repr(obj))
189 raise ValError( "%s n'est pas un repertoire valide" % repr(obj))
190 elif type_permis == 'FichierOuRepertoire':
193 if os.path.isdir(obj) or os.path.isfile(obj): return obj
194 else: raise ValError( "%s n'est pas un fichier ou un repertoire valide" % repr(obj))
196 raise ValError( "%s n'est pas un fichier ou un repertoire valide" % repr(obj))
197 elif type(type_permis) == type or isinstance(type_permis, type):
199 if self.isObjectFrom(obj, type_permis):
201 except Exception as err:
203 elif isinstance(type_permis, A_TUPLE.Tuple):
205 if type_permis.__convert__(obj):
207 except Exception as err:
209 elif isinstance(type_permis, object):
211 if type_permis.__convert__(obj):
213 except Exception as err:
216 print(("Type non encore gere %s" %type_permis))
218 tr("%s (de type %s) n'est pas d'un type autorise: %s ") % (repr(obj), type(obj), typ))
219 #import traceback; traceback.print_stack()
220 #print (object, type_permis,)
222 def isComplexe(self, valeur):
223 """ Retourne 1 si valeur est un complexe, 0 sinon """
225 # Pour permettre l'utilisation de complexes Python (accepte les
228 elif type(valeur) != tuple:
229 # On n'autorise pas les listes pour les complexes
231 elif len(valeur) != 3:
234 # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
235 # valeur suivie de 2 reels.
236 if valeur[0].strip() in ('RI', 'MP'):
238 v1 = reelProto.adapt(valeur[1]), reelProto.adapt(valeur[2])
245 def isObjectFrom(self, objet, classe):
247 Retourne 1 si objet est une instance de la classe classe, 0 sinon
249 convert = getattr(classe, '__convert__', None)
250 if convert is not None:
251 # classe verifie les valeurs
255 except ValueError as err:
259 # On accepte les instances de la classe et des classes derivees
260 return isinstance(objet, classe)
262 reelProto = TypeProtocol("reel", typ=('R',))
265 class CardProtocol(PProtocol):
267 """Verificateur de cardinalité """
268 # pas de registre par instance. Registre unique pour toutes les instances
271 def __init__(self, name, min=1, max=1):
272 PProtocol.__init__(self, name, min=min, max=max)
274 def default(self, obj, min, max):
276 if (length < min) or( length > max):
278 "Nombre d'arguments de %s incorrect (min = %s, max = %s)" % (repr(obj), min, max))
282 class IntoProtocol(PProtocol):
284 """Verificateur de choix possibles : liste discrète ou intervalle"""
285 # pas de registre par instance. Registre unique pour toutes les instances
288 def __init__(self, name, into=None, val_min=float('-inf'), val_max=float('inf')):
291 self, name, into=into, val_min=val_min, val_max=val_max)
292 self.val_min = val_min
293 self.val_max = val_max
295 def default(self, obj, into, val_min, val_max):
296 if type(into) ==types.FunctionType :
297 maListeDeValeur=into()
302 tr("La valeur : %s ne fait pas partie des choix possibles %s") % (repr(obj), into))
304 # on est dans le cas d'un ensemble continu de valeurs possibles
306 if isFloat_or_int(obj):
311 if obj < val_min or obj > val_max:
313 tr("La valeur : %s est en dehors du domaine de validite [ %s , %s ]") %(repr(obj), self.val_min, self.val_max))
317 class MinStr(object):
318 # exemple de classe pour verificateur de type
319 # on utilise des instances de classe comme type (typ=MinStr(3,6), par
322 def __init__(self, min, max):
326 def __convert__(self, valeur):
327 if isStr(valeur) and self.min <= len(valeur) <= self.max: return valeur
329 "%s n'est pas une chaine de longueur comprise entre %s et %s" % (valeur, self.min, self.max))
332 return tr("TXM de longueur entre %s et %s" % (self.min, self.max))
335 class Valid(PProtocol):
338 Cette classe est la classe mere des validateurs Accas
339 Elle doit etre derivee
340 Elle presente la signature des methodes indispensables pour son bon
341 fonctionnement et dans certains cas leur comportement par défaut.
343 @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
348 def __init__(self, **args):
349 PProtocol.__init__(self, "valid", **args)
353 Cette methode retourne une chaine de caractères informative sur
354 la validation demandée par le validateur. Elle est utilisée
355 pour produire le compte-rendu de validité du mot clé associé.
357 return "valeur valide"
361 Cette methode retourne une chaine de caractère qui permet
362 de construire un message d'aide en ligne.
363 En général, le message retourné est le meme que celui retourné par la
368 def infoErreurItem(self):
370 Cette méthode permet d'avoir un message d'erreur pour un item
371 dans une liste dans le cas ou le validateur fait des vérifications
372 sur les items d'une liste. Si le validateur fait seulement des
373 vérifications sur la liste elle meme et non sur ses items, la méthode
374 doit retourner une chaine vide.
378 def infoErreurListe(self):
380 Cette méthode a un comportement complémentaire de celui de
381 infoErreurItem. Elle retourne un message d'erreur lié uniquement
382 aux vérifications sur la liste elle meme et pas sur ses items.
383 Dans le cas où le validateur ne fait pas de vérification sur des
384 listes, elle retourne une chaine vide
388 def verif(self, valeur):
390 Cette methode sert a verifier si la valeur passee en argument est consideree
391 comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
392 (valide) sinon 0 (invalide).
394 @type valeur: tout type python
395 @param valeur: valeur du mot cle a valider
397 @return: indicateur de validite 1 (valide) ou 0 (invalide)
399 raise NotImplementedError("Must be implemented")
401 def verifItem(self, valeur):
403 La methode verif du validateur effectue une validation complete de
404 la valeur. valeur peut etre un scalaire ou une liste. Le validateur
405 doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
406 methode isList doit retourner 1).
407 La methode valid_item sert pour effectuer des validations partielles
408 de liste. Elle doit uniquement verifier la validite d'un item de
409 liste mais pas les caracteristiques de la liste.
413 def valideListePartielle(self, liste_courante):
415 Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
416 ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
417 veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
419 En général un validateur effectue la meme validation pour les listes partielles et les
422 return self.verif(liste_courante)
426 Cette methode sert a realiser des verifications du validateur lui meme.
427 Elle est facultative et retourne 1 (valide) par defaut.
428 Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
429 parametres de definition ne sont pas corrects.
430 La raison de l'invalidite est stockee dans l'attribut cata_info.
433 @return: indicateur de validite 1 (valide) ou 0 (invalide)
439 Cette méthode retourne un entier qui indique si le validateur
440 permet les listes (valeur 1) ou ne les permet pas (valeur 0).
441 Par défaut, un validateur n'autorise que des scalaires.
447 Cette méthode retourne un entier qui indique si le validateur
448 propose une liste de choix (valeur 1) ou n'en propose pas.
449 Par défaut, un validateur n'en propose pas.
453 def getInto(self, liste_courante=None, into_courant=None):
455 Cette méthode retourne la liste de choix proposée par le validateur.
456 Si le validateur ne propose pas de liste de choix, la méthode
458 L'argument d'entrée liste_courante, s'il est différent de None, donne
459 la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
460 méthode getInto doit calculer la liste des choix en en tenant
461 compte. Par exemple, si le validateur n'autorise pas les répétitions,
462 la liste des choix retournée ne doit pas contenir les choix déjà
463 contenus dans liste_courante.
464 L'argument d'entrée into_courant, s'il est différent de None, donne
465 la liste des choix proposés par d'autres validateurs. Dans ce cas,
466 la méthode getInto doit calculer la liste des choix à retourner
467 en se limitant à cette liste initiale. Par exemple, si into_courant
468 vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
469 la méthode ne doit retourner que (3,).
471 La méthode getInto peut retourner une liste vide [], ce qui veut
472 dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
473 peut etre normale : l''utilisateur a utilisé tous les choix, ou
474 résulter d'une incohérence des validateurs :
475 choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
476 faire la différence entre ces deux situations.
481 class ListVal(Valid):
484 Cette classe sert de classe mère pour tous les validateurs qui acceptent
491 def getInto(self, liste_courante=None, into_courant=None):
493 Cette méthode getInto effectue un traitement général qui consiste
494 a filtrer la liste de choix into_courant, si elle existe, en ne
495 conservant que les valeurs valides (appel de la méthode valid).
497 if into_courant is None:
501 for e in into_courant:
503 liste_choix.append(e)
506 def convert(self, valeur):
508 Méthode convert pour les validateurs de listes. Cette méthode
509 fait appel à la méthode convertItem sur chaque élément de la
512 if isSequence(valeur):
514 self.convertItem(val)
517 return self.convertItem(valeur)
519 def verif(self, valeur):
521 Méthode verif pour les validateurs de listes. Cette méthode
522 fait appel à la méthode verifItem sur chaque élément de la
523 liste. Si valeur est un paramètre, on utilise sa valeur effective
526 if isSequence(valeur):
528 if not self.verifItem(val):
532 return self.verifItem(valeur)
535 class Compulsory(ListVal):
537 Validateur operationnel
538 Verification de la présence obligatoire d'un élément dans une liste
542 def __init__(self, elem=()):
543 if not isSequence(elem):
545 Valid.__init__(self, elem=elem)
550 return (tr(u"valeur %s obligatoire") % self.elem)
552 def default(self, valeur, elem):
555 def verifItem(self, valeur):
558 def convert(self, valeur):
559 elem = list(self.elem)
566 tr("%s ne contient pas les elements obligatoires : %s ") % (valeur, elem))
572 def verif(self, valeur):
573 if not isSequence(valeur):
577 for val in self.elem:
582 def infoErreurItem(self):
583 return tr("La valeur n'est pas dans la liste des choix possibles")
586 class Together(ListVal):
588 Validateur operationnel
589 si un des éléments est présent les autres doivent aussi l'être
593 def __init__(self, elem=()):
594 if not isSequence(elem):
596 Valid.__init__(self, elem=elem)
601 return (tr("%s present ensemble") % self.elem)
603 def default(self, valeur, elem):
606 def verifItem(self, valeur):
609 def convert(self, valeur):
610 elem = list(self.elem)
613 if v in elem: elem.remove(v)
614 if ( len(elem) == 0 ): return valeur
615 if len(elem) != len(list(self.elem)) :
616 raise ValError(tr("%s ne contient pas les elements devant etre presents ensemble: %s ") %( valeur, elem))
622 def verif(self, valeur):
623 if not isSequence(valeur):
628 for val in self.elem:
629 if val in liste: compte += 1
630 if ( compte == 0 ): return 1
631 if ( compte != len( list(self.elem) ) ): return 0
634 def infoErreurItem(self):
635 return tr("La valeur n'est pas dans la liste des choix possibles")
638 class Absent(ListVal):
640 Validateur operationnel
641 si un des éléments est présent non valide
645 def __init__(self, elem=()):
646 if not isSequence(elem):
648 Valid.__init__(self, elem=elem)
653 return (tr("%s absent") % self.elem)
655 def default(self, valeur, elem):
658 def verifItem(self, valeur):
661 def convert(self, valeur):
662 elem = list(self.elem)
666 raise ValError(tr("%s n'est pas autorise : %s ")% (v, elem))
672 def verif(self, valeur):
673 if not isSequence(valeur):
677 for val in self.elem:
678 if val in liste: return 0
681 def infoErreurItem(self):
682 return tr("La valeur n'est pas dans la liste des choix possibles")
685 class NoRepeat(ListVal):
687 Validateur operationnel
688 Verification d'absence de doublons dans la liste.
695 return tr("Pas de doublon dans la liste")
697 def infoErreurListe(self):
698 return tr("Les doublons ne sont pas permis")
700 def default(self, valeur):
701 if valeur in self.liste:
702 raise ValError( tr("%s est un doublon") % valeur)
705 def convert(self, valeur):
712 def verifItem(self, valeur):
715 def verif(self, valeur):
716 if isSequence(valeur):
719 if liste.count(val) != 1:
725 def getInto(self, liste_courante=None, into_courant=None):
727 Methode getInto spécifique pour validateur NoRepeat, on retourne
728 une liste de choix qui ne contient aucune valeur de into_courant
729 déjà contenue dans liste_courante
731 if into_courant is None:
735 for e in into_courant:
738 if liste_courante is not None and e in liste_courante:
740 liste_choix.append(e)
744 class LongStr(ListVal):
747 Validateur operationnel
748 Verification de la longueur d une chaine
751 def __init__(self, low, high):
752 ListVal.__init__(self, low=low, high=high)
758 return (tr("longueur de la chaine entre %s et %s") %( self.low, self.high))
760 def infoErreurItem(self):
761 return tr("Longueur de la chaine incorrecte")
763 def convert(self, valeur):
768 def verifItem(self, valeur):
775 def default(self, valeur, low, high):
776 if not isStr(valeur):
777 raise ValError ("%s n'est pas une chaine" % repr(valeur))
778 if valeur[0] == "'" and valeur[-1] == "'":
781 if len(valeur) < low or len(valeur) > high:
783 "%s n'est pas de la bonne longueur" % repr(valeur))
787 class OnlyStr(ListVal):
790 Validateur operationnel
791 Valide que c'est une chaine
795 ListVal.__init__(self)
799 return tr("regarde si c'est une chaine")
801 def infoErreurItem(self):
802 return tr("Ce n'est pas une chaine")
804 def convert(self, valeur):
809 def verifItem(self, valeur):
816 def default(self, valeur):
817 if not isStr(valeur):
818 raise ValError (tr("%s n'est pas une chaine") % repr(valeur))
822 class OrdList(ListVal):
825 Validateur operationnel
826 Verification qu'une liste est croissante ou decroissante
829 def __init__(self, ord):
830 ListVal.__init__(self, ord=ord)
835 return ("liste %s" % self.ord)
837 def infoErreurListe(self):
838 return (tr("La liste doit etre en ordre %s") % self.ord)
840 def convert(self, valeur):
847 def default(self, valeur, ord):
848 if self.ord == 'croissant':
849 if self.val is not None and valeur < self.val:
851 (tr("%s n'est pas par valeurs croissantes") % repr(self.liste)))
852 elif self.ord == 'decroissant':
853 if self.val is not None and valeur > self.val:
855 (tr("%s n'est pas par valeurs decroissantes") % repr(self.liste)))
859 def verifItem(self, valeur):
862 def getInto(self, liste_courante=None, into_courant=None):
864 Methode getInto spécifique pour validateur OrdList, on retourne
865 une liste de choix qui ne contient aucune valeur de into_courant
866 dont la valeur est inférieure à la dernière valeur de
867 liste_courante, si elle est différente de None.
869 if into_courant is None:
871 elif not liste_courante:
875 last_val = liste_choix[-1]
876 for e in into_courant:
877 if self.ord == 'croissant' and e <= last_val:
879 if self.ord == 'decroissant' and e >= last_val:
881 liste_choix.append(e)
888 Validateur operationnel
889 Cette classe est un validateur qui controle une liste de validateurs
890 Elle verifie qu'au moins un des validateurs de la liste valide la valeur
893 def __init__(self, validators=()):
894 if not isSequence(validators):
895 validators = (validators,)
897 for validator in validators:
898 if type(validator) == types.FunctionType:
899 self.validators.append(FunctionVal(validator))
901 self.validators.append(validator)
905 return "\n ou ".join([v.info() for v in self.validators])
907 def convert(self, valeur):
908 for validator in self.validators:
910 return validator.convert(valeur)
913 raise ValError(tr("%s n'est pas du bon type")% repr(valeur))
915 def infoErreurItem(self):
917 for v in self.validators:
918 err = v.infoErreurItem()
921 chaine = " \n ou ".join(l)
924 def infoErreurListe(self):
926 for v in self.validators:
927 err = v.infoErreurListe()
930 chaine = " \n ou ".join(l)
935 Si plusieurs validateurs sont reliés par un OU
936 il suffit qu'un seul des validateurs attende une liste
937 pour qu'on considère que leur union attend une liste.
939 for validator in self.validators:
940 v = validator.isList()
945 def verif(self, valeur):
946 for validator in self.validators:
947 v = validator.verif(valeur)
952 def verifItem(self, valeur):
953 for validator in self.validators:
954 v = validator.verifItem(valeur)
961 for validator in self.validators:
962 v = validator.verifCata()
964 infos.append(validator.cata_info)
966 self.cata_info = "\n".join(infos)
973 Dans le cas ou plusieurs validateurs sont reliés par un OU
974 il faut que tous les validateurs proposent un choix pour
975 qu'on considère que leur union propose un choix.
976 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
977 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
979 for validator in self.validators:
980 v = validator.hasInto()
985 def getInto(self, liste_courante=None, into_courant=None):
987 Dans le cas ou plusieurs validateurs sont reliés par un OU
988 tous les validateurs doivent proposer un choix pour
989 qu'on considère que leur union propose un choix. Tous les choix
990 proposés par les validateurs sont réunis (opérateur d'union).
991 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
992 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
996 for validator in self.validators:
997 v_into = validator.getInto(liste_courante, into_courant)
1000 validator_into.extend(v_into)
1001 return validator_into
1003 def valideListePartielle(self, liste_courante=None):
1005 Méthode de validation de liste partielle pour le validateur Or.
1006 Si un des validateurs gérés par le validateur Or considère la
1007 liste comme valide, le validateur Or la considère comme valide.
1009 for validator in self.validators:
1010 v = validator.valideListePartielle(liste_courante)
1016 class AndVal(Valid):
1019 Validateur operationnel
1020 Cette classe est un validateur qui controle une liste de validateurs
1021 Elle verifie que tous les validateurs de la liste valident la valeur
1024 def __init__(self, validators=()):
1025 if not isSequence(validators):
1026 validators = (validators,)
1027 self.validators = []
1028 for validator in validators:
1029 if type(validator) == types.FunctionType:
1030 self.validators.append(FunctionVal(validator))
1032 self.validators.append(validator)
1033 if hasattr(validator, 'fonctions'):
1034 for fonction in validator.fonctions:
1035 f = getattr(validator, fonction)
1036 setattr(self, fonction, f)
1040 return "\n et ".join([v.info() for v in self.validators])
1042 def convert(self, valeur):
1043 for validator in self.validators:
1044 valeur = validator.convert(valeur)
1047 def infoErreurItem(self):
1050 for v in self.validators:
1051 if v.infoErreurItem() != " ":
1053 chaine = v.infoErreurItem()
1056 chaine = chaine + " \n et " + v.infoErreurItem()
1059 def infoErreurListe(self):
1062 for v in self.validators:
1063 if v.infoErreurListe() != " ":
1065 chaine = v.infoErreurListe()
1068 chaine = chaine + " \n et " + v.infoErreurListe()
1071 def verif(self, valeur):
1072 for validator in self.validators:
1073 v = validator.verif(valeur)
1075 self.local_info = validator.info()
1079 def verifItem(self, valeur):
1080 for validator in self.validators:
1081 v = validator.verifItem(valeur)
1083 # L'info n'est probablement pas la meme que pour verif ???
1084 self.local_info = validator.info()
1088 def verifCata(self):
1090 for validator in self.validators:
1091 v = validator.verifCata()
1093 infos.append(validator.cata_info)
1095 self.cata_info = "\n".join(infos)
1100 def valideListePartielle(self, liste_courante=None):
1102 Méthode de validation de liste partielle pour le validateur And.
1103 Tous les validateurs gérés par le validateur And doivent considérer
1104 la liste comme valide, pour que le validateur And la considère
1107 for validator in self.validators:
1108 v = validator.valideListePartielle(liste_courante)
1115 Si plusieurs validateurs sont reliés par un ET
1116 il faut que tous les validateurs attendent une liste
1117 pour qu'on considère que leur intersection attende une liste.
1118 Exemple Range(2,5) ET Card(1) n'attend pas une liste
1119 Range(2,5) ET Pair attend une liste
1121 for validator in self.validators:
1122 v = validator.isList()
1129 Dans le cas ou plusieurs validateurs sont reliés par un ET
1130 il suffit qu'un seul validateur propose un choix pour
1131 qu'on considère que leur intersection propose un choix.
1132 Exemple : Enum(1,2,3) ET entier pair, propose un choix
1133 En revanche, entier pair ET superieur à 10 ne propose pas de choix
1135 for validator in self.validators:
1136 v = validator.hasInto()
1141 def getInto(self, liste_courante=None, into_courant=None):
1143 Dans le cas ou plusieurs validateurs sont reliés par un ET
1144 il suffit qu'un seul validateur propose un choix pour
1145 qu'on considère que leur intersection propose un choix. Tous les
1146 choix proposés par les validateurs sont croisés (opérateur
1148 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
1149 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
1151 for validator in self.validators:
1152 into_courant = validator.getInto(liste_courante, into_courant)
1153 if into_courant in ([], None):
1158 def do_liste(validators):
1160 Convertit une arborescence de validateurs en OrVal ou AndVal
1161 validators est une liste de validateurs ou de listes ou de tuples
1164 for validator in validators:
1165 if type(validator) == types.FunctionType:
1166 valids.append(FunctionVal(validator))
1167 elif type(validator) is tuple:
1168 valids.append(OrVal(do_liste(validator)))
1169 elif type(validator) is list:
1170 valids.append(AndVal(do_liste(validator)))
1172 valids.append(validator)
1176 def validatorFactory(validator):
1177 if type(validator) == types.FunctionType:
1178 return FunctionVal(validator)
1179 elif type(validator) is tuple:
1180 return OrVal(do_liste(validator))
1181 elif type(validator) is list:
1182 return AndVal(do_liste(validator))
1186 # Ci-dessous : exemples de validateur (peu testés)
1189 class RangeVal(ListVal):
1192 Exemple de classe validateur : verification qu'une valeur
1193 est dans un intervalle.
1194 Pour une liste on verifie que tous les elements sont
1196 Susceptible de remplacer les attributs "vale_min" "vale_max"
1200 def __init__(self, low, high):
1203 self.cata_info = (tr("%s doit etre inferieur a %s") % (low, high))
1206 return (tr("valeur dans l'intervalle %s , %s") %( self.low, self.high))
1208 def convertItem(self, valeur):
1209 if valeur > self.low and valeur < self.high:
1211 raise ValError(tr("%s devrait etre comprise entre %s et %s") % (valeur, self.low, self.high))
1213 def verifItem(self, valeur):
1214 return valeur > self.low and valeur < self.high
1216 def infoErreurItem(self):
1217 return (tr("la valeur %s doit etre comprise entre %s et %s") % (valeur, self.low, self.high))
1220 def verifCata(self):
1221 if self.low > self.high:
1226 class CardVal(Valid):
1229 Exemple de classe validateur : verification qu'une liste est
1230 d'une longueur superieur a un minimum (min) et inferieure
1232 Susceptible de remplacer les attributs "min" "max" dans les
1236 def __init__(self, min=float('-inf'), max=float('inf')):
1239 self.cata_info = (tr("%s doit etre inferieur a %s") %(min, max))
1242 return (tr("longueur de liste comprise entre %s et %s") %(self.min, self.max))
1244 def infoErreurListe(self):
1245 return (tr("Le cardinal de la liste doit etre compris entre %s et %s") % (self.min, self.max))
1248 return self.max == '**' or self.max > 1
1250 def getInto(self, liste_courante=None, into_courant=None):
1251 if into_courant is None:
1253 elif liste_courante is None:
1255 elif self.max == '**':
1257 elif len(liste_courante) < self.max:
1262 def convert(self, valeur):
1263 if isSequence(valeur):
1265 elif valeur is None:
1269 if self.max != '**' and l > self.max:
1271 tr("%s devrait etre de longueur inferieure a %s") % (valeur, self.max))
1272 if self.min != '**' and l < self.min:
1274 tr("%s devrait etre de longueur superieure a %s") % (valeur, self.min))
1277 def verifItem(self, valeur):
1280 def verif(self, valeur):
1281 if isSequence(valeur):
1282 if self.max != '**' and len(valeur) > self.max:
1284 if self.min != '**' and len(valeur) < self.min:
1288 if self.max != '**' and 1 > self.max:
1290 if self.min != '**' and 1 < self.min:
1294 def verifCata(self):
1295 if self.min != '**' and self.max != '**' and self.min > self.max:
1299 def valideListePartielle(self, liste_courante=None):
1301 if liste_courante != None:
1302 if len(liste_courante) > self.max:
1307 class PairVal(ListVal):
1310 Exemple de classe validateur : verification qu'une valeur
1312 Pour une liste on verifie que tous les elements sont
1317 ListVal.__init__(self)
1321 return _(u"valeur paire")
1323 def infoErreurItem(self):
1324 return tr("La valeur saisie doit etre paire")
1326 def convert(self, valeur):
1331 tr("%s contient des valeurs non paires") % repr(valeur))
1334 def default(self, valeur):
1337 def verifItem(self, valeur):
1338 if type(valeur) not in six.integer_types:
1340 return valeur % 2 == 0
1342 def verif(self, valeur):
1343 if isSequence(valeur):
1354 class EnumVal(ListVal):
1357 Exemple de classe validateur : verification qu'une valeur
1358 est prise dans une liste de valeurs.
1359 Susceptible de remplacer l attribut "into" dans les catalogues
1362 def __init__(self, into=()):
1363 if not isSequence(into):
1369 return ("valeur dans %s" % self.into)
1371 def convertItem(self, valeur):
1372 if valeur in self.into:
1375 tr("%s contient des valeurs hors des choix possibles: %s ") % (valeur, self.into))
1377 def verifItem(self, valeur):
1378 if valeur not in self.into:
1385 def getInto(self, liste_courante=None, into_courant=None):
1386 if into_courant is None:
1387 liste_choix = list(self.into)
1390 for e in into_courant:
1392 liste_choix.append(e)
1395 def infoErreurItem(self):
1396 return tr("La valeur n'est pas dans la liste des choix possibles")
1399 def ImpairVal(valeur):
1401 Exemple de validateur
1402 Cette fonction est un validateur. Elle verifie que la valeur passee
1403 est bien un nombre impair.
1405 if isSequence(valeur):
1415 ImpairVal.info = "valeur impaire"
1421 Exemple de validateur
1422 Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1423 que la somme des cles A et B vaut une valeur donnee
1424 en parametre du validateur
1427 def __init__(self, somme=10):
1432 return (tr("valeur %s pour la somme des cles A et B ") % self.somme)
1434 def verif(self, valeur):
1435 if isSequence(valeur):
1441 if val["A"] + val["B"] != self.somme:
1445 if not "A" in valeur:
1447 if not "B" in valeur:
1449 if valeur["A"] + valeur["B"] != self.somme:
1454 class FunctionVal(Valid):
1457 Exemple de validateur
1458 Cette classe est un validateur qui est initialise avec une fonction
1461 def __init__(self, function):
1462 self.function = function
1465 return self.function.info
1467 def infoErreurItem(self):
1468 return self.function.info
1470 def verif(self, valeur):
1471 return self.function(valeur)
1473 def verifItem(self, valeur):
1474 return self.function(valeur)
1476 def convert(self, valeur):
1479 # MC ca ne devrait plus servir !
1480 # PN : commenter le 22.11.19
1481 #CoercableFuncs = {int: int,
1485 # str: six.text_type}
1489 class TypeVal(ListVal):
1492 Exemple de validateur
1493 Cette classe est un validateur qui controle qu'une valeur
1494 est bien du type Python attendu.
1495 Pour une liste on verifie que tous les elements sont du bon type.
1496 Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1497 alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1500 def __init__(self, aType):
1501 # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1502 # type(1) == int;type(0.2)==float;etc.
1503 if type(aType) != type:
1507 self.coerce = CoercableFuncs[aType]
1509 self.coerce = self.identity
1512 return (tr("valeur de %s") % self.aType)
1514 def identity(self, value):
1515 if type(value) == self.aType:
1519 def convertItem(self, valeur):
1520 return self.coerce(valeur)
1522 def verifItem(self, valeur):
1530 class InstanceVal(ListVal):
1533 Exemple de validateur
1534 Cette classe est un validateur qui controle qu'une valeur est
1535 bien une instance (au sens Python) d'une classe
1536 Pour une liste on verifie chaque element de la liste
1539 def __init__(self, aClass):
1540 # Si aClass est une classe on la memorise dans self.aClass
1541 # sinon c'est une instance dont on memorise la classe
1542 #if type(aClass) == types.InstanceType:
1543 if type(aClass) == object :
1544 # instance ancienne mode
1545 aClass = aClass.__class__
1546 elif type(aClass) == type:
1547 # classe ancienne mode
1549 elif type(aClass) == type:
1550 # classe nouvelle mode
1552 elif isinstance(aClass, object):
1553 # instance nouvelle mode
1554 aClass = type(aClass)
1556 raise ValError(tr("type non supporté"))
1558 self.aClass = aClass
1561 return (tr("valeur d'instance de %s") % self.aClass.__name__)
1563 def verifItem(self, valeur):
1564 if not isinstance(valeur, self.aClass):
1569 class VerifTypeTuple(ListVal):
1571 def __init__(self, typeDesTuples):
1572 self.typeDesTuples = typeDesTuples
1573 Valid.__init__(self)
1577 return tr(": verifie les \ntypes dans un tuple")
1579 def infoErreurListe(self):
1580 return tr("Les types entres ne sont pas permis")
1582 def default(self, valeur):
1588 def convertItem(self, valeur):
1589 if len(valeur) != len(self.typeDesTuples):
1591 tr("%s devrait etre de type %s ") %( valeur, self.typeDesTuples))
1592 for i in range(len(valeur)):
1593 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1596 tr("%s devrait etre de type %s ") % (valeur, self.typeDesTuples))
1599 def verifItem(self, valeur):
1601 if len(valeur) != len(self.typeDesTuples):
1603 for i in range(len(valeur)):
1604 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1611 def verifType(self, valeur, type_permis):
1612 if type_permis == 'R':
1613 if type(valeur) in (int, float, int):
1615 elif type_permis == 'I':
1616 if type(valeur) in (int, int):
1618 elif type_permis == 'C':
1619 if self.isComplexe(valeur):
1621 elif type_permis == 'TXM':
1622 if type(valeur) == bytes or type(valeur) == str:
1624 elif isinstance(valeur, type_permis):
1628 def verif(self, valeur):
1629 if type(valeur) in (list, tuple):
1630 liste = list(valeur)
1632 if self.verifItem(val) != 1:
1637 class VerifExiste(ListVal):
1640 fonctionne avec into
1641 Met une liste à jour selon les mot clefs existant
1642 exemple si into = ("A","B","C")
1643 si au niveau N du JDC les objets "A" et "C" existe
1644 alors la liste des into deviendra ( "A","C")
1646 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1647 niveauVerif est defini par rapport au Noeud :
1648 exemple niveauVerif = 1 : on verifie les freres
1649 niveauVerif = 2 : on verifie les oncles..
1652 def __init__(self, niveauVerif):
1653 ListVal.__init__(self)
1654 self.niveauVerif = niveauVerif
1656 self.listeDesFreres = ()
1657 self.fonctions = ('verifieListe', 'set_MCSimp')
1662 def verifieListe(self, liste):
1663 self.set_MCSimp(self.MCSimp)
1665 if not(item in self.listeDesFreres):
1669 def verifItem(self, valeur):
1670 self.set_MCSimp(self.MCSimp)
1671 if valeur in self.listeDesFreres:
1675 def set_MCSimp(self, MCSimp):
1676 self.MCSimp = MCSimp
1677 k = self.niveauVerif
1683 # on met la liste à jour
1684 parent.forceRecalcul = self.niveauVerif
1685 self.listeDesFreres = parent.listeMcPresents()
1687 def convertItem(self, valeur):
1688 if valeur in self.listeDesFreres:
1691 tr("%s n'est pas dans %s") % (valeur, self.listeDesFreres))
1694 class RegExpVal(ListVal):
1697 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1700 errormsg = 'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1702 def __init__(self, pattern):
1703 self.pattern = pattern
1704 self.compiled_regexp = re.compile(pattern)
1707 return tr('Une chaîne correspondant au motif ') + str(self.pattern) + tr(" est attendue")
1709 def infoErreurItem(self):
1710 return tr('Une chaîne correspondant au motif ') + str(self.pattern) + tr(" est attendue")
1712 def verifItem(self, valeur):
1713 if self.compiled_regexp.match(valeur):
1716 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1718 def convertItem(self, valeur):
1719 if self.compiled_regexp.match(valeur):
1722 raise ValError(self.errormsg %
1723 {"value": valeur, "pattern": self.pattern})
1726 class FileExtVal(RegExpVal):
1729 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1732 def __init__(self, ext):
1734 self.errormsg = '"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1736 #PNPN Modif pour Adao
1737 RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
1741 return ('Un nom de fichier se terminant par ".%s" est attendu.' % self.ext)
1743 def infoErreurItem(self):
1744 return ('Un nom de fichier se terminant par ".%s" est attendu.' % self.ext)
1746 class CreeMotClef(object):
1747 def __init__(self,MotClef ):
1748 self.MotClef=MotClef
1751 def convert(self, lval):
1752 try : valeur=lval[0]
1753 except : return lval
1755 parent= self.MCSimp.parent
1756 if hasattr(parent, 'inhibeValidator') and parent.inhibeValidator: return lval
1759 if parent.getChild(self.MotClef) == None : longueur=0
1760 else : longueur=len(parent.getChild(self.MotClef))
1762 pos=parent.getIndexChild(self.MCSimp.nom)+1
1763 while longueur < valeur :
1764 parent.inhibeValidator=1
1765 parent.addEntite(self.MotClef,pos)
1767 parent.inhibeValidator=0
1768 longueur=len(parent.getChild(self.MotClef))
1770 if longueur > valeur :
1771 parent.inhibeValide=1
1772 parentObj=parent.getChild(self.MotClef)
1773 obj=parent.getChild(self.MotClef)[-1]
1774 parentObj.suppEntite(obj)
1775 longueur=len(parent.getChild(self.MotClef))
1776 parent.inhibeValide=0
1780 return "Cree le bon nombre de Mot %s" % self.MotClef
1782 def verifItem(self, valeur):
1785 def set_MCSimp(self, MCSimp):
1786 #print "dans set_MCSimp"