1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2013 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 Ce module contient toutes les classes necessaires pour
22 implanter le concept de validateur dans Accas
27 from N_ASSD import ASSD
28 from N_types import is_int, is_float_or_int, is_complex, is_number, is_str, is_enum
29 from strfunc import convert
30 from Extensions.i18n import tr
32 class ValError(Exception):pass
35 if hasattr(cls,"__mro__"):return cls.__mro__
37 for base in cls.__bases__:
38 mro.extend(cls_mro(base))
42 def __init__(self,name):
47 def register(self, T, A):
51 # (a) verifier si l'objet peut s'adapter au protocole
52 adapt = getattr(obj, '__adapt__', None)
54 # on demande à l'objet obj de réaliser lui-meme l'adaptation
57 # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
59 for T in cls_mro(obj.__class__):
60 if T in self.registry:
61 return self.registry[T](obj,self,**self.args)
63 # (c) utiliser l'adapteur par defaut
64 return self.default(obj,**self.args)
66 def default(self,obj,**args):
67 raise TypeError("Can't adapt %s to %s" %
68 (obj.__class__.__name__, self.name))
70 class PProtocol(Protocol):
71 """Verificateur de protocole paramétré (classe de base)"""
72 #Protocole paramétré. Le registre est unique pour toutes les instances. La methode register est une methode de classe
74 def __init__(self,name,**args):
77 def register(cls, T, A):
79 register=classmethod(register)
81 class ListProtocol(Protocol):
82 """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
83 def default(self,obj):
84 if type(obj) is tuple:
85 if len(obj) > 0 and obj[0] in ('RI','MP'):
86 #il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
90 elif type(obj) is list:
93 # pas de valeur affecte. La cardinalite vaut 0
96 #il s'agit d'une chaine. La cardinalite vaut 1
100 # si l'objet supporte len, on a la cardinalite
107 listProto=ListProtocol("list")
110 class TypeProtocol(PProtocol):
111 """Verificateur de type parmi une liste de types possibles"""
112 #pas de registre par instance. Registre unique pour toutes les instances de TypeProtocol
114 def __init__(self,name,typ=None):
115 PProtocol.__init__(self,name,typ=typ)
118 def default(self,obj,typ):
121 for type_permis in typ:
122 if type_permis == 'R':
123 if is_float_or_int(obj): return obj
124 elif type_permis == 'I':
125 if is_int(obj): return obj
126 elif type_permis == 'C':
127 if self.is_complexe(obj): return obj
128 elif type_permis == 'TXM':
129 if is_str(obj): return obj
130 elif type_permis == 'shell':
131 if is_str(obj): return obj
132 elif type_permis == 'Fichier' :
134 if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj):
136 #else : raise ValError(ufmt(_(u"%s n'est pas un fichier valide"), repr(obj)))
137 else : raise ValError(repr(obj)+tr(" n'est pas un fichier valide"))
138 elif type_permis == 'FichierNoAbs' :
140 if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")):
142 #else : raise ValError(ufmt(_(u"%s n'est pas un fichier valide"), repr(obj)))
143 else : raise ValError(repr(obj)+tr(" n'est pas un fichier valide"))
144 elif type_permis == 'Repertoire':
146 if os.path.isdir(obj):
149 #raise ValError(ufmt(_(u"%s n'est pas un répertoire valide"), repr(obj)))
150 raise ValError(repr(obj)+tr(" n'est pas un repertoire valide"))
151 elif type(type_permis) == types.ClassType or isinstance(type_permis,type):
153 if self.is_object_from(obj,type_permis): return obj
154 except Exception, err:
156 elif type(type_permis) == types.InstanceType or isinstance(type_permis,object):
158 if type_permis.__convert__(obj): return obj
159 except Exception, err:
162 #print convert(ufmt(_(u"Type non encore géré %s"), `type_permis`))
163 print tr("Type non encore gere "), `type_permis`
164 #raise ValError(ufmt(_(u"%s (de type %s) n'est pas d'un type autorisé: %s %s"),
165 #repr(obj), type(obj), typ, unicode(err)))
166 raise ValError(repr(obj) +tr("de type ") + repr(type(obj)) + tr (" n'est pas d'un type autorise: ")+ str(typ) + " " + unicode(err))
168 def is_complexe(self,valeur):
169 """ Retourne 1 si valeur est un complexe, 0 sinon """
170 if is_number(valeur):
171 # Pour permettre l'utilisation de complexes Python (accepte les entiers et réels)
173 elif type(valeur) != tuple :
174 # On n'autorise pas les listes pour les complexes
176 elif len(valeur) != 3:
179 # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
180 # valeur suivie de 2 reels.
181 if valeur[0].strip() in ('RI','MP'):
183 v1=reelProto.adapt(valeur[1]),reelProto.adapt(valeur[2])
190 def is_object_from(self,objet,classe):
192 Retourne 1 si objet est une instance de la classe classe, 0 sinon
194 convert = getattr(classe, '__convert__', None)
195 if convert is not None:
196 # classe verifie les valeurs
200 except ValueError, err:
204 # On accepte les instances de la classe et des classes derivees
205 return isinstance(objet,classe)
207 reelProto=TypeProtocol("reel",typ=('R',))
209 class CardProtocol(PProtocol):
210 """Verificateur de cardinalité """
211 #pas de registre par instance. Registre unique pour toutes les instances
213 def __init__(self,name,min=1,max=1):
214 PProtocol.__init__(self,name,min=min,max=max)
216 def default(self,obj,min,max):
218 if length < min or length >max:
219 #raise ValError(ufmt(_(u"Nombre d'arguments de %s incorrect (min = %s, max = %s)"),
220 # repr(obj), min, max))
221 raise ValError(tr("Nombre incorrect d'arguments de ")+repr(obj)+"min = "+repr(min)+" max ="+repr(max))
224 class IntoProtocol(PProtocol):
225 """Verificateur de choix possibles : liste discrète ou intervalle"""
226 #pas de registre par instance. Registre unique pour toutes les instances
228 def __init__(self,name,into=None,val_min='**',val_max='**'):
229 PProtocol.__init__(self,name,into=into,val_min=val_min,val_max=val_max)
233 def default(self,obj,into,val_min,val_max):
236 #raise ValError(ufmt(_(u"La valeur : %s ne fait pas partie des choix possibles %s"),
238 raise ValError(tr("La valeur :") +repr(obj)+ tr(" ne fait pas partie des choix possibles ") + repr(into))
240 #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
241 if is_float_or_int(obj):
242 if val_min == '**': val_min = obj -1
243 if val_max == '**': val_max = obj +1
244 if obj < val_min or obj > val_max :
245 #raise ValError(ufmt(_(u"La valeur : %s est en dehors du domaine de validité [ %s , %s ]"),
246 # repr(obj), self.val_min, self.val_max))
247 raise ValError(tr("La valeur :") +repr(obj)+ tr(" est en dehors du domaine de validite [ ") + repr(self.val_min) + "," + repr(self.val_max) + "]")
251 #exemple de classe pour verificateur de type
252 #on utilise des instances de classe comme type (typ=MinStr(3,6), par exemple)
253 def __init__(self,min,max):
257 def __convert__(self,valeur):
258 if is_str(valeur) and self.min <= len(valeur) <= self.max:return valeur
259 raise ValError(ufmt(_(u"%s n'est pas une chaine de longueur comprise entre %s et %s"),
260 valeur, self.min, self.max))
261 raise ValError(valeur + tr(" n'est pas une chaine de longueur comprise entre ") + repr(self.min) + " et " + repr(self.max))
264 #return ufmt(_(u"TXM de longueur entre %s et %s"), self.min, self.max)
265 return tr(" TXM de longueur entre ")+ repr(self.min) + " et " + repr(self.max)
267 class Valid(PProtocol):
269 Cette classe est la classe mere des validateurs Accas
270 Elle doit etre derivee
271 Elle presente la signature des methodes indispensables pour son bon
272 fonctionnement et dans certains cas leur comportement par défaut.
274 @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
275 @type cata_info: C{string}
278 def __init__(self,**args):
279 PProtocol.__init__(self,"valid",**args)
283 Cette methode retourne une chaine de caractères informative sur
284 la validation demandée par le validateur. Elle est utilisée
285 pour produire le compte-rendu de validité du mot clé associé.
287 #return _(u"valeur valide")
288 return tr("valeur valide")
292 Cette methode retourne une chaine de caractère qui permet
293 de construire un message d'aide en ligne.
294 En général, le message retourné est le meme que celui retourné par la
299 def info_erreur_item(self):
301 Cette méthode permet d'avoir un message d'erreur pour un item
302 dans une liste dans le cas ou le validateur fait des vérifications
303 sur les items d'une liste. Si le validateur fait seulement des
304 vérifications sur la liste elle meme et non sur ses items, la méthode
305 doit retourner une chaine vide.
309 def info_erreur_liste(self):
311 Cette méthode a un comportement complémentaire de celui de
312 info_erreur_item. Elle retourne un message d'erreur lié uniquement
313 aux vérifications sur la liste elle meme et pas sur ses items.
314 Dans le cas où le validateur ne fait pas de vérification sur des
315 listes, elle retourne une chaine vide
319 def verif(self,valeur):
321 Cette methode sert a verifier si la valeur passee en argument est consideree
322 comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
323 (valide) sinon 0 (invalide).
325 @type valeur: tout type python
326 @param valeur: valeur du mot cle a valider
328 @return: indicateur de validite 1 (valide) ou 0 (invalide)
330 raise NotImplementedError("Must be implemented")
332 def verif_item(self,valeur):
334 La methode verif du validateur effectue une validation complete de
335 la valeur. valeur peut etre un scalaire ou une liste. Le validateur
336 doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
337 methode is_list doit retourner 1).
338 La methode valid_item sert pour effectuer des validations partielles
339 de liste. Elle doit uniquement verifier la validite d'un item de
340 liste mais pas les caracteristiques de la liste.
344 def valide_liste_partielle(self,liste_courante):
346 Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
347 ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
348 veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
350 En général un validateur effectue la meme validation pour les listes partielles et les
353 return self.verif(liste_courante)
355 def verif_cata(self):
357 Cette methode sert a realiser des verifications du validateur lui meme.
358 Elle est facultative et retourne 1 (valide) par defaut.
359 Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
360 parametres de definition ne sont pas corrects.
361 La raison de l'invalidite est stockee dans l'attribut cata_info.
364 @return: indicateur de validite 1 (valide) ou 0 (invalide)
370 Cette méthode retourne un entier qui indique si le validateur
371 permet les listes (valeur 1) ou ne les permet pas (valeur 0).
372 Par défaut, un validateur n'autorise que des scalaires.
378 Cette méthode retourne un entier qui indique si le validateur
379 propose une liste de choix (valeur 1) ou n'en propose pas.
380 Par défaut, un validateur n'en propose pas.
384 def get_into(self,liste_courante=None,into_courant=None):
386 Cette méthode retourne la liste de choix proposée par le validateur.
387 Si le validateur ne propose pas de liste de choix, la méthode
389 L'argument d'entrée liste_courante, s'il est différent de None, donne
390 la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
391 méthode get_into doit calculer la liste des choix en en tenant
392 compte. Par exemple, si le validateur n'autorise pas les répétitions,
393 la liste des choix retournée ne doit pas contenir les choix déjà
394 contenus dans liste_courante.
395 L'argument d'entrée into_courant, s'il est différent de None, donne
396 la liste des choix proposés par d'autres validateurs. Dans ce cas,
397 la méthode get_into doit calculer la liste des choix à retourner
398 en se limitant à cette liste initiale. Par exemple, si into_courant
399 vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
400 la méthode ne doit retourner que (3,).
402 La méthode get_into peut retourner une liste vide [], ce qui veut
403 dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
404 peut etre normale : l''utilisateur a utilisé tous les choix, ou
405 résulter d'une incohérence des validateurs :
406 choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
407 faire la différence entre ces deux situations.
411 class ListVal(Valid):
413 Cette classe sert de classe mère pour tous les validateurs qui acceptent
419 def get_into(self,liste_courante=None,into_courant=None):
421 Cette méthode get_into effectue un traitement général qui consiste
422 a filtrer la liste de choix into_courant, si elle existe, en ne
423 conservant que les valeurs valides (appel de la méthode valid).
425 if into_courant is None:
429 for e in into_courant:
431 liste_choix.append(e)
434 def convert(self,valeur):
436 Méthode convert pour les validateurs de listes. Cette méthode
437 fait appel à la méthode convert_item sur chaque élément de la
442 self.convert_item(val)
445 return self.convert_item(valeur)
447 def verif(self,valeur):
449 Méthode verif pour les validateurs de listes. Cette méthode
450 fait appel à la méthode verif_item sur chaque élément de la
451 liste. Si valeur est un paramètre, on utilise sa valeur effective
456 if not self.verif_item(val):
460 return self.verif_item(valeur)
462 class Compulsory(ListVal):
464 Validateur operationnel
465 Verification de la présence obligatoire d'un élément dans une liste
468 def __init__(self,elem=()):
469 if not is_enum(elem): elem=(elem,)
470 Valid.__init__(self,elem=elem)
475 #return ufmt(_(u"valeur %s obligatoire"), `self.elem`)
476 return tr("valeur obligatoire")
478 def default(self,valeur,elem):
481 def verif_item(self,valeur):
484 def convert(self,valeur):
488 if v in elem:elem.remove(v)
490 #raise ValError(ufmt(_(u"%s ne contient pas les elements obligatoires : %s "),
492 raise ValError(valeur + tr(" ne contient pas les elements obligatoires : ")+ elem)
498 def verif(self,valeur):
499 if not is_enum(valeur):
503 for val in self.elem :
504 if val not in liste : return 0
507 def info_erreur_item(self):
508 #return _(u"La valeur n'est pas dans la liste des choix possibles")
509 return tr("La valeur n'est pas dans la liste des choix possibles")
511 class NoRepeat(ListVal):
513 Validateur operationnel
514 Verification d'absence de doublons dans la liste.
521 #return _(u": pas de présence de doublon dans la liste")
522 return tr(": pas de presence de doublon dans la liste")
524 def info_erreur_liste(self):
525 #return _(u"Les doublons ne sont pas permis")
526 return tr("Les doublons ne sont pas permis")
528 def default(self,valeur):
529 if valeur in self.liste :
530 #raise ValError(ufmt(_(u"%s est un doublon"), valeur))
531 raise ValError(repr(valeur) + tr(" est un doublon"))
534 def convert(self,valeur):
541 def verif_item(self,valeur):
544 def verif(self,valeur):
548 if liste.count(val)!=1 : return 0
553 def get_into(self,liste_courante=None,into_courant=None):
555 Methode get_into spécifique pour validateur NoRepeat, on retourne
556 une liste de choix qui ne contient aucune valeur de into_courant
557 déjà contenue dans liste_courante
559 if into_courant is None:
563 for e in into_courant:
564 if e in liste_choix: continue
565 if liste_courante is not None and e in liste_courante: continue
566 liste_choix.append(e)
569 class LongStr(ListVal):
571 Validateur operationnel
572 Verification de la longueur d une chaine
574 def __init__(self,low,high):
575 ListVal.__init__(self,low=low,high=high)
581 #return ufmt(_(u"longueur de la chaine entre %s et %s"), self.low, self.high)
582 return tr("longueur de la chaine entre")+ self.low + tr(" et ")+ self.high
584 def info_erreur_item(self):
585 #return _(u"Longueur de la chaine incorrecte")
586 return tr("Longueur de la chaine incorrecte")
588 def convert(self,valeur):
593 def verif_item(self,valeur):
600 def default(self,valeur,low,high):
601 if not is_str(valeur):
602 #raise ValError(ufmt(_(u"%s n'est pas une chaine"), repr(valeur)))
603 raise ValError( repr(valeur) + tr(" n'est pas une chaine"))
604 if valeur[0]=="'" and valeur[-1]=="'" :
607 if len(valeur) < low or len(valeur) > high :
608 #raise ValError(ufmt(_(u"%s n'est pas de la bonne longueur"), repr(valeur)))
609 raise ValError( repr(valeur) + tr(" n'est pas de la bonne longueur"))
612 class OnlyStr(ListVal):
614 Validateur operationnel
615 Valide que c'est une chaine
618 ListVal.__init__(self)
622 #return _(u"regarde si c'est une chaine")
623 return tr("verifier que c'est une chaine")
625 def info_erreur_item(self):
626 #return _(u"Ce n'est pas une chaine")
627 return tr("Ce n'est pas une chaine")
629 def convert(self,valeur):
634 def verif_item(self,valeur):
641 def default(self,valeur):
642 if not is_str(valeur):
643 #raise ValError(ufmt(_(u"%s n'est pas une chaine"), repr(valeur)))
644 raise ValError(repr(valeur) + tr(" n'est pas une chaine"))
647 class OrdList(ListVal):
649 Validateur operationnel
650 Verification qu'une liste est croissante ou decroissante
652 def __init__(self,ord):
653 ListVal.__init__(self,ord=ord)
658 #return ufmt(_(u"liste %s"), self.ord)
659 return tr("liste ") + self.ord
661 def info_erreur_liste(self) :
662 #return ufmt(_(u"La liste doit etre en ordre %s"), self.ord)
663 return tr("La liste doit etre en ordre ")+ self.ord
665 def convert(self,valeur):
672 def default(self,valeur,ord):
673 if self.ord=='croissant':
674 if self.val is not None and valeur<self.val:
675 #raise ValError(ufmt(_(u"%s n'est pas par valeurs croissantes"), repr(self.liste)))
676 raise ValError(repr(self.liste) +tr(" n'est pas par valeurs croissantes"))
677 elif self.ord=='decroissant':
678 if self.val is not None and valeur > self.val:
679 #raise ValError(ufmt(_(u"%s n'est pas par valeurs decroissantes"), repr(self.liste)))
680 raise ValError(repr(self.liste) +tr(" n'est pas par valeurs decroissantes"))
684 def verif_item(self,valeur):
687 def get_into(self,liste_courante=None,into_courant=None):
689 Methode get_into spécifique pour validateur OrdList, on retourne
690 une liste de choix qui ne contient aucune valeur de into_courant
691 dont la valeur est inférieure à la dernière valeur de
692 liste_courante, si elle est différente de None.
694 if into_courant is None:
696 elif not liste_courante :
700 last_val=liste_choix[-1]
701 for e in into_courant:
702 if self.ord=='croissant' and e <= last_val:continue
703 if self.ord=='decroissant' and e >= last_val:continue
704 liste_choix.append(e)
709 Validateur operationnel
710 Cette classe est un validateur qui controle une liste de validateurs
711 Elle verifie qu'au moins un des validateurs de la liste valide la valeur
713 def __init__(self,validators=()):
714 if not is_enum(validators):
715 validators=(validators,)
717 for validator in validators:
718 if type(validator) == types.FunctionType:
719 self.validators.append(FunctionVal(validator))
721 self.validators.append(validator)
725 return "\n ou ".join([v.info() for v in self.validators])
727 def convert(self,valeur):
728 for validator in self.validators:
730 return validator.convert(valeur)
733 raise ValError(ufmt(_(u"%s n'est pas du bon type"), repr(valeur)))
734 raise ValError(repr(valeur) + tr(" n'est pas du bon type"))
736 def info_erreur_item(self):
738 for v in self.validators:
739 err=v.info_erreur_item()
740 if err != " " : l.append(err)
741 chaine=" \n ou ".join(l)
744 def info_erreur_liste(self):
746 for v in self.validators:
747 err=v.info_erreur_liste()
748 if err != " " : l.append(err)
749 chaine=" \n ou ".join(l)
754 Si plusieurs validateurs sont reliés par un OU
755 il suffit qu'un seul des validateurs attende une liste
756 pour qu'on considère que leur union attend une liste.
758 for validator in self.validators:
759 v=validator.is_list()
764 def verif(self,valeur):
765 for validator in self.validators:
766 v=validator.verif(valeur)
771 def verif_item(self,valeur):
772 for validator in self.validators:
773 v=validator.verif_item(valeur)
778 def verif_cata(self):
780 for validator in self.validators:
781 v=validator.verif_cata()
782 if not v :infos.append(validator.cata_info)
784 self.cata_info="\n".join(infos)
791 Dans le cas ou plusieurs validateurs sont reliés par un OU
792 il faut que tous les validateurs proposent un choix pour
793 qu'on considère que leur union propose un choix.
794 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
795 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
797 for validator in self.validators:
798 v=validator.has_into()
803 def get_into(self,liste_courante=None,into_courant=None):
805 Dans le cas ou plusieurs validateurs sont reliés par un OU
806 tous les validateurs doivent proposer un choix pour
807 qu'on considère que leur union propose un choix. Tous les choix
808 proposés par les validateurs sont réunis (opérateur d'union).
809 Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
810 En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
814 for validator in self.validators:
815 v_into=validator.get_into(liste_courante,into_courant)
818 validator_into.extend(v_into)
819 return validator_into
821 def valide_liste_partielle(self,liste_courante=None):
823 Méthode de validation de liste partielle pour le validateur Or.
824 Si un des validateurs gérés par le validateur Or considère la
825 liste comme valide, le validateur Or la considère comme valide.
827 for validator in self.validators:
828 v=validator.valide_liste_partielle(liste_courante)
835 Validateur operationnel
836 Cette classe est un validateur qui controle une liste de validateurs
837 Elle verifie que tous les validateurs de la liste valident la valeur
839 def __init__(self,validators=()):
840 if not is_enum(validators):
841 validators=(validators,)
843 for validator in validators:
844 if type(validator) == types.FunctionType:
845 self.validators.append(FunctionVal(validator))
847 self.validators.append(validator)
848 if hasattr(validator,'fonctions'):
849 for fonction in validator.fonctions :
850 f=getattr(validator,fonction)
851 setattr(self,fonction,f)
855 return "\n et ".join([v.info() for v in self.validators])
857 def convert(self,valeur):
858 for validator in self.validators:
859 valeur=validator.convert(valeur)
862 def info_erreur_item(self):
865 for v in self.validators:
866 if v.info_erreur_item() != " " :
868 chaine=v.info_erreur_item()
871 chaine=chaine+" \n et "+v.info_erreur_item()
874 def info_erreur_liste(self):
876 for v in self.validators:
877 if v.info_erreur_liste() != " " :
879 chaine=v.info_erreur_liste()
882 chaine=chaine+" \n et "+v.info_erreur_liste()
885 def verif(self,valeur):
886 for validator in self.validators:
887 v=validator.verif(valeur)
889 self.local_info=validator.info()
893 def verif_item(self,valeur):
894 for validator in self.validators:
895 v=validator.verif_item(valeur)
897 # L'info n'est probablement pas la meme que pour verif ???
898 self.local_info=validator.info()
902 def verif_cata(self):
904 for validator in self.validators:
905 v=validator.verif_cata()
906 if not v :infos.append(validator.cata_info)
908 self.cata_info="\n".join(infos)
913 def valide_liste_partielle(self,liste_courante=None):
915 Méthode de validation de liste partielle pour le validateur And.
916 Tous les validateurs gérés par le validateur And doivent considérer
917 la liste comme valide, pour que le validateur And la considère
920 for validator in self.validators:
921 v=validator.valide_liste_partielle(liste_courante)
928 Si plusieurs validateurs sont reliés par un ET
929 il faut que tous les validateurs attendent une liste
930 pour qu'on considère que leur intersection attende une liste.
931 Exemple Range(2,5) ET Card(1) n'attend pas une liste
932 Range(2,5) ET Pair attend une liste
934 for validator in self.validators:
935 v=validator.is_list()
942 Dans le cas ou plusieurs validateurs sont reliés par un ET
943 il suffit qu'un seul validateur propose un choix pour
944 qu'on considère que leur intersection propose un choix.
945 Exemple : Enum(1,2,3) ET entier pair, propose un choix
946 En revanche, entier pair ET superieur à 10 ne propose pas de choix
948 for validator in self.validators:
949 v=validator.has_into()
954 def get_into(self,liste_courante=None,into_courant=None):
956 Dans le cas ou plusieurs validateurs sont reliés par un ET
957 il suffit qu'un seul validateur propose un choix pour
958 qu'on considère que leur intersection propose un choix. Tous les
959 choix proposés par les validateurs sont croisés (opérateur
961 Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
962 En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
964 for validator in self.validators:
965 into_courant=validator.get_into(liste_courante,into_courant)
966 if into_courant in ([],None):break
969 def do_liste(validators):
971 Convertit une arborescence de validateurs en OrVal ou AndVal
972 validators est une liste de validateurs ou de listes ou de tuples
975 for validator in validators:
976 if type(validator) == types.FunctionType:
977 valids.append(FunctionVal(validator))
978 elif type(validator) is tuple:
979 valids.append(OrVal(do_liste(validator)))
980 elif type(validator) is list:
981 valids.append(AndVal(do_liste(validator)))
983 valids.append(validator)
986 def validatorFactory(validator):
987 if type(validator) == types.FunctionType:
988 return FunctionVal(validator)
989 elif type(validator) is tuple:
990 return OrVal(do_liste(validator))
991 elif type(validator) is list:
992 return AndVal(do_liste(validator))
996 # Ci-dessous : exemples de validateur (peu testés)
998 class RangeVal(ListVal):
1000 Exemple de classe validateur : verification qu'une valeur
1001 est dans un intervalle.
1002 Pour une liste on verifie que tous les elements sont
1004 Susceptible de remplacer les attributs "vale_min" "vale_max"
1007 def __init__(self,low,high):
1010 #self.cata_info=ufmt(_(u"%s doit être inférieur a %s"), low,high)
1011 self.cata_info=low + tr(" doit être inférieur a ")+ high
1014 #return ufmt(_(u"valeur dans l'intervalle %s , %s"), self.low, self.high)
1015 return tr(" valeur dans l 'intervalle ")+self.low+ self.high
1017 def convert_item(self,valeur):
1018 if valeur > self.low and valeur < self.high:return valeur
1019 #raise ValError(ufmt(_(u"%s devrait être comprise entre %s et %s"),
1020 # valeur, self.low, self.high))
1021 raise ValError(valeur + tr(" devrait etre comprise entre ") + self.low + tr(" et ")+ self.high)
1023 def verif_item(self,valeur):
1024 return valeur > self.low and valeur < self.high
1026 def info_erreur_item(self) :
1027 #return ufmt(_(u"La valeur doit etre comprise entre %s et %s"), self.low, self.high)
1028 return tr("La valeur doit etre comprise entre ") + self.low + tr(" et ") + self.high
1030 def verif_cata(self):
1031 if self.low > self.high : return 0
1034 class CardVal(Valid):
1036 Exemple de classe validateur : verification qu'une liste est
1037 d'une longueur superieur a un minimum (min) et inferieure
1039 Susceptible de remplacer les attributs "min" "max" dans les
1042 def __init__(self,min='**',max='**'):
1045 self.cata_info=min + tr(" doit etre inferieur a ")+ max
1046 #self.cata_info= ufmt(_(u"%s doit etre inferieur a %s"), min,max)
1049 #return ufmt(_(u"longueur de liste comprise entre %s et %s"), self.min, self.max)
1050 return tr("La longueur doit etre comprise entre ") + self.min + tr(" et ") + self.max
1052 def info_erreur_liste(self):
1053 #return ufmt(_(u"Le cardinal de la liste doit etre compris entre %s et %s"),
1054 # self.min, self.max)
1055 return tr("Le cardinal de la liste doit etre compris entre ") + self.min + tr(" et ") + self.max
1058 return self.max == '**' or self.max > 1
1060 def get_into(self,liste_courante=None,into_courant=None):
1061 if into_courant is None:
1063 elif liste_courante is None:
1065 elif self.max == '**':
1067 elif len(liste_courante) < self.max:
1072 def convert(self,valeur):
1075 elif valeur is None:
1079 if self.max != '**' and l > self.max:
1080 #raise ValError(ufmt(_(u"%s devrait etre de longueur inferieure a %s"), valeur, self.max))
1081 raise ValError(valeur + tr(" devrait etre de longueur inferieure a ")+ self.min)
1082 if self.min != '**' and l < self.min:
1083 #raise ValError(ufmt(_(u"%s devrait etre de longueur superieure a %s"), valeur, self.min))
1084 raise ValError(valeur + tr(" devrait etre de longueur superieure a ")+ self.max)
1087 def verif_item(self,valeur):
1090 def verif(self,valeur):
1092 if self.max != '**' and len(valeur) > self.max:return 0
1093 if self.min != '**' and len(valeur) < self.min:return 0
1096 if self.max != '**' and 1 > self.max:return 0
1097 if self.min != '**' and 1 < self.min:return 0
1100 def verif_cata(self):
1101 if self.min != '**' and self.max != '**' and self.min > self.max : return 0
1104 def valide_liste_partielle(self,liste_courante=None):
1106 if liste_courante != None :
1107 if len(liste_courante) > self.max :
1111 class PairVal(ListVal):
1113 Exemple de classe validateur : verification qu'une valeur
1115 Pour une liste on verifie que tous les elements sont
1119 ListVal.__init__(self)
1123 #return _(u"valeur paire")
1124 return tr("valeur paire")
1126 def info_erreur_item(self):
1127 #return _(u"La valeur saisie doit etre paire")
1128 return tr("La valeur saisie doit etre paire")
1130 def convert(self,valeur):
1134 #raise ValError(ufmt(_(u"%s contient des valeurs non paires"), repr(valeur)))
1135 raise ValError(repr(valeur)+tr("contient des valeurs non paires"))
1138 def default(self,valeur):
1141 def verif_item(self,valeur):
1142 if type(valeur) not in (int,long):
1144 return valeur % 2 == 0
1146 def verif(self,valeur):
1149 if val % 2 != 0:return 0
1152 if valeur % 2 != 0:return 0
1155 class EnumVal(ListVal):
1157 Exemple de classe validateur : verification qu'une valeur
1158 est prise dans une liste de valeurs.
1159 Susceptible de remplacer l attribut "into" dans les catalogues
1161 def __init__(self,into=()):
1162 if not is_enum(into):
1168 #return "valeur dans %s" % `self.into`
1169 return tr("valeur dans") + self.into
1171 def convert_item(self,valeur):
1172 if valeur in self.into:return valeur
1173 #raise ValError(ufmt(_(u"%s contient des valeurs hors des choix possibles: %s "),
1174 # valeur, self.into))
1175 raise ValError(valeur + tr(" contient des valeurs hors des choix possibles: ")+ self.into)
1177 def verif_item(self,valeur):
1178 if valeur not in self.into:return 0
1184 def get_into(self,liste_courante=None,into_courant=None):
1185 if into_courant is None:
1186 liste_choix= list(self.into)
1189 for e in into_courant:
1191 liste_choix.append(e)
1194 def info_erreur_item(self):
1195 #return _(u"La valeur n'est pas dans la liste des choix possibles")
1196 return tr("La valeur n'est pas dans la liste des choix possibles")
1198 def ImpairVal(valeur):
1200 Exemple de validateur
1201 Cette fonction est un validateur. Elle verifie que la valeur passee
1202 est bien un nombre impair.
1206 if val % 2 != 1:return 0
1209 if valeur % 2 != 1:return 0
1212 ImpairVal.info="valeur impaire"
1216 Exemple de validateur
1217 Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1218 que la somme des cles A et B vaut une valeur donnee
1219 en parametre du validateur
1221 def __init__(self,somme=10):
1226 #return ufmt(_(u"valeur %s pour la somme des cles A et B "), self.somme)
1227 return tr("valeur") + repr(self.somme) + tr(" pour la somme des cles A et B ")
1229 def verif(self,valeur):
1232 if not val.has_key("A"):return 0
1233 if not val.has_key("B"):return 0
1234 if val["A"]+val["B"] != self.somme:return 0
1237 if not valeur.has_key("A"):return 0
1238 if not valeur.has_key("B"):return 0
1239 if valeur["A"]+valeur["B"] != self.somme:return 0
1242 class FunctionVal(Valid):
1244 Exemple de validateur
1245 Cette classe est un validateur qui est initialise avec une fonction
1247 def __init__(self,function):
1248 self.function=function
1251 return self.function.info
1253 def verif(self,valeur):
1254 return self.function(valeur)
1256 #MC ca ne devrait plus servir !
1257 CoercableFuncs = { types.IntType: int,
1258 types.LongType: long,
1259 types.FloatType: float,
1260 types.ComplexType: complex,
1261 types.UnicodeType: unicode }
1263 class TypeVal(ListVal):
1265 Exemple de validateur
1266 Cette classe est un validateur qui controle qu'une valeur
1267 est bien du type Python attendu.
1268 Pour une liste on verifie que tous les elements sont du bon type.
1269 Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1270 alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1272 def __init__(self, aType):
1273 #Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1274 #type(1) == int;type(0.2)==float;etc.
1275 if type(aType) != types.TypeType:
1279 self.coerce=CoercableFuncs[ aType ]
1281 self.coerce = self.identity
1284 #return ufmt(_(u"valeur de %s"), self.aType)
1285 return tr("valeur de ")+ self.aType
1287 def identity ( self, value ):
1288 if type( value ) == self.aType:
1292 def convert_item(self,valeur):
1293 return self.coerce(valeur)
1295 def verif_item(self,valeur):
1302 class InstanceVal(ListVal):
1304 Exemple de validateur
1305 Cette classe est un validateur qui controle qu'une valeur est
1306 bien une instance (au sens Python) d'une classe
1307 Pour une liste on verifie chaque element de la liste
1309 def __init__(self,aClass):
1310 #Si aClass est une classe on la memorise dans self.aClass
1311 #sinon c'est une instance dont on memorise la classe
1312 if type(aClass) == types.InstanceType:
1313 #instance ancienne mode
1314 aClass=aClass.__class__
1315 elif type(aClass) == types.ClassType:
1316 #classe ancienne mode
1318 elif type(aClass) == type:
1319 #classe nouvelle mode
1321 elif isinstance(aClass,object):
1322 #instance nouvelle mode
1325 raise ValError(_(u"type non supporté"))
1330 #return ufmt(_(u"valeur d'instance de %s"), self.aClass.__name__)
1331 return tr("valeur d'instance de ")+ self.aClass.__name__
1333 def verif_item(self,valeur):
1334 if not isinstance(valeur,self.aClass): return 0
1337 class VerifTypeTuple(Valid,ListVal) :
1338 def __init__(self,typeDesTuples):
1339 self.typeDesTuples=typeDesTuples
1340 Valid.__init__(self)
1344 return _(u": vérifie les types dans un tuple")
1346 def info_erreur_liste(self):
1347 return _(u"Les types entrés ne sont pas permis")
1349 def default(self,valeur):
1350 #if valeur in self.liste : raise ValError("%s est un doublon" % valeur)
1356 def convert_item(self,valeur):
1357 if len(valeur) != len(self.typeDesTuples):
1358 #raise ValError(ufmt(_(u"%s devrait etre de type %s "), valeur, repr(self.typeDesTuples)))
1359 raise ValError(repr(valeur)+tr(" devrait etre de type ")+ self.typeDesTuples)
1360 for i in range(len(valeur)) :
1361 ok=self.verifType(valeur[i],self.typeDesTuples[i])
1363 #raise ValError(ufmt(_(u"%s devrait etre de type %s "), valeur, self.typeDesTuples))
1364 raise ValError(repr(valeur)+tr(" devrait etre de type ")+ self.typeDesTuples)
1367 def verif_item(self,valeur):
1369 if len(valeur) != len(self.typeDesTuples):
1371 for i in range(len(valeur)) :
1372 ok=self.verifType(valeur[i],self.typeDesTuples[i])
1379 def verifType(self,valeur,type_permis):
1380 if type_permis == 'R':
1381 if type(valeur) in (types.IntType,types.FloatType,types.LongType):return 1
1382 elif type_permis == 'I':
1383 if type(valeur) in (types.IntType,types.LongType):return 1
1384 elif type_permis == 'C':
1385 if self.is_complexe(valeur):return 1
1386 elif type_permis == 'TXM':
1387 if type(valeur)==types.StringType:return 1
1390 def verif(self,valeur):
1391 if type(valeur) in (types.ListType,types.TupleType):
1394 if self.verif_item(val)!=1 : return 0
1397 class VerifExiste(ListVal) :
1399 fonctionne avec into
1400 Met une liste à jour selon les mot clefs existant
1401 exemple si into = ("A","B","C")
1402 si au niveau N du JDC les objets "A" et "C" existe
1403 alors la liste des into deviendra ( "A","C")
1405 niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1406 niveauVerif est defini par rapport au Noeud :
1407 exemple niveauVerif = 1 : on verifie les freres
1408 niveauVerif = 2 : on verifie les oncles..
1410 def __init__(self,niveauVerif):
1411 ListVal.__init__(self)
1412 self.niveauVerif=niveauVerif
1414 self.listeDesFreres=()
1415 self.fonctions=('verifie_liste','set_MCSimp')
1420 def verifie_liste(self,liste):
1421 self.set_MCSimp(self.MCSimp)
1423 if not( item in self.listeDesFreres) : return 0
1426 def verif_item(self,valeur):
1427 self.set_MCSimp(self.MCSimp)
1428 if valeur in self.listeDesFreres : return 1
1431 def set_MCSimp(self, MCSimp) :
1439 #on met la liste à jour
1440 parent.forceRecalcul=self.niveauVerif
1441 self.listeDesFreres=parent.liste_mc_presents()
1443 def convert_item(self,valeur):
1444 if valeur in self.listeDesFreres : return valeur
1445 raise ValError(ufmt(_(u"%s n'est pas dans %s"), valeur, self.listeDesFreres))
1447 class RegExpVal(ListVal):
1449 Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1452 errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1454 def __init__(self, pattern):
1455 self.pattern = pattern
1456 self.compiled_regexp = re.compile(pattern)
1459 return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
1461 def verif_item(self, valeur):
1462 if self.compiled_regexp.match(valeur):
1465 return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1467 def convert_item(self, valeur):
1468 if self.compiled_regexp.match(valeur):
1471 raise ValError(self.errormsg % {"value": valeur, "pattern": self.pattern})
1473 class FileExtVal(RegExpVal):
1475 Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1478 def __init__(self, ext):
1480 self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {"ext": ext}
1481 RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
1484 #return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext
1485 return tr('Un nom de fichier se terminant par') + self.ext +tr(" est attendu.")