]> SALOME platform Git repositories - tools/eficas.git/blob - Noyau/N_VALIDATOR.py
Salome HOME
traduction
[tools/eficas.git] / Noyau / N_VALIDATOR.py
1 # coding=utf-8
2 # Copyright (C) 2007-2015   EDF R&D
3 #
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.
8 #
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.
13 #
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
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20
21 # ======================================================================
22
23 """
24    Ce module contient toutes les classes necessaires pour
25    implanter le concept de validateur dans Accas
26 """
27 import types
28 import traceback
29 import re
30 from N_ASSD import ASSD
31 from N_types import is_int, is_float_or_int, is_complex, is_number, is_str, is_sequence
32 from strfunc import convert, ufmt
33 from Extensions.i18n import tr
34
35
36
37 class ValError(Exception):
38     pass
39
40
41 def cls_mro(cls):
42     if hasattr(cls, "__mro__"):
43         return cls.__mro__
44     mro = [cls]
45     for base in cls.__bases__:
46         mro.extend(cls_mro(base))
47     return mro
48
49
50 class Protocol:
51
52     def __init__(self, name):
53         self.registry = {}
54         self.name = name
55         self.args = {}
56
57     def register(self, T, A):
58         self.registry[T] = A
59
60     def adapt(self, obj):
61         # (a) verifier si l'objet peut s'adapter au protocole
62         adapt = getattr(obj, '__adapt__', None)
63         if adapt is not None:
64             # on demande à l'objet obj de réaliser lui-meme l'adaptation
65             return adapt(self)
66
67         # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
68         if self.registry:
69             for T in cls_mro(obj.__class__):
70                 if T in self.registry:
71                     return self.registry[T](obj, self, **self.args)
72
73         # (c) utiliser l'adapteur par defaut
74         return self.default(obj, **self.args)
75
76     def default(self, obj, **args):
77         raise TypeError("Can't adapt %s to %s" %
78                         (obj.__class__.__name__, self.name))
79
80
81 class PProtocol(Protocol):
82
83     """Verificateur de protocole paramétré (classe de base)"""
84     # Protocole paramétré. Le registre est unique pour toutes les instances.
85     # La methode register est une methode de classe
86     registry = {}
87
88     def __init__(self, name, **args):
89         self.name = name
90         self.args = args
91
92     def register(cls, T, A):
93         cls.registry[T] = A
94     register = classmethod(register)
95
96
97 class ListProtocol(Protocol):
98
99     """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
100
101     def default(self, obj):
102         if type(obj) is tuple:
103             if len(obj) > 0 and obj[0] in ('RI', 'MP'):
104                 # il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
105                 return (obj,)
106             else:
107                 return obj
108         elif type(obj) is list:
109             return obj
110         elif obj == None:
111             # pas de valeur affecte. La cardinalite vaut 0
112             return obj
113         elif is_str(obj):
114             # il s'agit d'une chaine. La cardinalite vaut 1
115             return (obj,)
116         else:
117             try:
118                 # si l'objet supporte len, on a la cardinalite
119                 length = len(obj)
120                 return obj
121             except:
122                 # sinon elle vaut 1
123                 return (obj,)
124
125 listProto = ListProtocol("list")
126
127
128 class TypeProtocol(PProtocol):
129
130     """Verificateur de type parmi une liste de types possibles"""
131     # pas de registre par instance. Registre unique pour toutes les instances
132     # de TypeProtocol
133     registry = {}
134
135     def __init__(self, name, typ=None):
136         PProtocol.__init__(self, name, typ=typ)
137         self.typ = typ
138
139     def default(self, obj, typ):
140
141         err = ""
142         for type_permis in typ:
143             if type_permis == 'R':
144                 if is_float_or_int(obj):
145                     return obj
146             elif type_permis == 'I':
147                 if is_int(obj):
148                     return obj
149             elif type_permis == 'C':
150                 if self.is_complexe(obj):
151                     return obj
152             elif type_permis == 'TXM':
153                 if is_str(obj):
154                     return obj
155             elif type_permis == 'shell':
156                 if is_str(obj):
157                     return obj
158             elif type_permis == 'Fichier':
159                 import os
160                 if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj):
161                     return obj
162                 else:
163                     raise ValError(
164                         ufmt(_(tr(u"%s n'est pas un fichier valide")), repr(obj)))
165             elif type_permis == 'FichierNoAbs':
166                 import os
167                 if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")):
168                     return obj
169                 else:
170                     raise ValError(
171                         ufmt(_(tr("%s n'est pas un fichier valide")), repr(obj)))
172             elif type_permis == 'Repertoire':
173                 import os
174                 if os.path.isdir(obj):
175                     return obj
176                 else:
177                     raise ValError(
178                         ufmt(_(tr(u"%s n'est pas un repertoire valide")), repr(obj)))
179             elif type(type_permis) == types.ClassType or isinstance(type_permis, type):
180                 try:
181                     if self.is_object_from(obj, type_permis):
182                         return obj
183                 except Exception, err:
184                     pass
185             elif type(type_permis) == types.InstanceType or isinstance(type_permis, object):
186                 try:
187                     if type_permis.__convert__(obj):
188                         return obj
189                 except Exception, err:
190                     pass
191             else:
192                 print convert(ufmt(_(tr(u"Type non encore gere %s")), `type_permis`))
193         raise ValError(
194             ufmt(_(tr(u"%s (de type %s) n'est pas d'un type autorise: %s %s")),
195                  repr(obj), type(obj), typ, unicode(err)))
196
197     def is_complexe(self, valeur):
198         """ Retourne 1 si valeur est un complexe, 0 sinon """
199         if is_number(valeur):
200             # Pour permettre l'utilisation de complexes Python (accepte les
201             # entiers et réels)
202             return 1
203         elif type(valeur) != tuple:
204             # On n'autorise pas les listes pour les complexes
205             return 0
206         elif len(valeur) != 3:
207             return 0
208         else:
209             # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
210             # valeur suivie de 2 reels.
211             if valeur[0].strip() in ('RI', 'MP'):
212                 try:
213                     v1 = reelProto.adapt(valeur[1]), reelProto.adapt(valeur[2])
214                     return 1
215                 except:
216                     return 0
217             else:
218                 return 0
219
220     def is_object_from(self, objet, classe):
221         """
222            Retourne 1 si objet est une instance de la classe classe, 0 sinon
223         """
224         convert = getattr(classe, '__convert__', None)
225         if convert is not None:
226             # classe verifie les valeurs
227             try:
228                 v = convert(objet)
229                 return v is not None
230             except ValueError, err:
231                 raise
232             except:
233                 return 0
234         # On accepte les instances de la classe et des classes derivees
235         return isinstance(objet, classe)
236
237 reelProto = TypeProtocol("reel", typ=('R',))
238
239
240 class CardProtocol(PProtocol):
241
242     """Verificateur de cardinalité """
243     # pas de registre par instance. Registre unique pour toutes les instances
244     registry = {}
245
246     def __init__(self, name, min=1, max=1):
247         PProtocol.__init__(self, name, min=min, max=max)
248
249     def default(self, obj, min, max):
250         length = len(obj)
251         if length < min or length > max:
252             raise ValError(
253                 ufmt(
254                     _(tr(u"Nombre d'arguments de %s incorrect (min = %s, max = %s)")),
255                     repr(obj), min, max))
256         return obj
257
258
259 class IntoProtocol(PProtocol):
260
261     """Verificateur de choix possibles : liste discrète ou intervalle"""
262     # pas de registre par instance. Registre unique pour toutes les instances
263     registry = {}
264
265     def __init__(self, name, into=None, val_min='**', val_max='**'):
266         PProtocol.__init__(
267             self, name, into=into, val_min=val_min, val_max=val_max)
268         self.val_min = val_min
269         self.val_max = val_max
270
271     def default(self, obj, into, val_min, val_max):
272         if into:
273             if obj not in into:
274                 raise ValError(
275                     ufmt(
276                         _(tr(u"La valeur : %s  ne fait pas partie des choix possibles %s")),
277                         repr(obj), into))
278         else:
279             # on est dans le cas d'un ensemble continu de valeurs possibles
280             # (intervalle)
281             if is_float_or_int(obj):
282                 if val_min == '**':
283                     val_min = obj - 1
284                 if val_max == '**':
285                     val_max = obj + 1
286                 if obj < val_min or obj > val_max:
287                     raise ValError(
288                         ufmt(
289                             _(tr(u"La valeur : %s est en dehors du domaine de validite [ %s , %s ]")),
290                             repr(obj), self.val_min, self.val_max))
291         return obj
292
293
294 class MinStr:
295     # exemple de classe pour verificateur de type
296     # on utilise des instances de classe comme type (typ=MinStr(3,6), par
297     # exemple)
298
299     def __init__(self, min, max):
300         self.min = min
301         self.max = max
302
303     def __convert__(self, valeur):
304         if is_str(valeur) and self.min <= len(valeur) <= self.max:
305             return valeur
306         raise ValError(
307             ufmt(
308                 _(tr(u"%s n'est pas une chaine de longueur comprise entre %s et %s")),
309                 valeur, self.min, self.max))
310
311     def __repr__(self):
312         return ufmt(_(tr(u"TXM de longueur entre %s et %s")), self.min, self.max)
313
314
315 class Valid(PProtocol):
316
317     """
318          Cette classe est la classe mere des validateurs Accas
319          Elle doit etre derivee
320          Elle presente la signature des methodes indispensables pour son bon
321          fonctionnement et dans certains cas leur comportement par défaut.
322
323          @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
324          @type cata_info: C{string}
325     """
326     registry = {}
327
328     def __init__(self, **args):
329         PProtocol.__init__(self, "valid", **args)
330
331     def info(self):
332         """
333            Cette methode retourne une chaine de caractères informative sur
334            la validation demandée par le validateur. Elle est utilisée
335            pour produire le compte-rendu de validité du mot clé associé.
336         """
337         return _(u"valeur valide")
338
339     def aide(self):
340         """
341            Cette methode retourne une chaine de caractère qui permet
342            de construire un message d'aide en ligne.
343            En général, le message retourné est le meme que celui retourné par la
344            méthode info.
345         """
346         return self.info()
347
348     def info_erreur_item(self):
349         """
350            Cette méthode permet d'avoir un message d'erreur pour un item
351            dans une liste dans le cas ou le validateur fait des vérifications
352            sur les items d'une liste. Si le validateur fait seulement des
353            vérifications sur la liste elle meme et non sur ses items, la méthode
354            doit retourner une chaine vide.
355         """
356         return " "
357
358     def info_erreur_liste(self):
359         """
360            Cette méthode a un comportement complémentaire de celui de
361            info_erreur_item. Elle retourne un message d'erreur lié uniquement
362            aux vérifications sur la liste elle meme et pas sur ses items.
363            Dans le cas où le validateur ne fait pas de vérification sur des
364            listes, elle retourne une chaine vide
365         """
366         return " "
367
368     def verif(self, valeur):
369         """
370             Cette methode sert a verifier si la valeur passee en argument est consideree
371             comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
372             (valide) sinon 0 (invalide).
373
374             @type valeur: tout type python
375             @param valeur: valeur du mot cle a valider
376             @rtype: C{boolean}
377             @return: indicateur de validite 1 (valide) ou 0 (invalide)
378         """
379         raise NotImplementedError("Must be implemented")
380
381     def verif_item(self, valeur):
382         """
383            La methode verif du validateur effectue une validation complete de
384            la valeur. valeur peut etre un scalaire ou une liste. Le validateur
385            doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
386            methode is_list doit retourner 1).
387            La methode valid_item sert pour effectuer des validations partielles
388            de liste. Elle doit uniquement verifier la validite d'un item de
389            liste mais pas les caracteristiques de la liste.
390         """
391         return 0
392
393     def valide_liste_partielle(self, liste_courante):
394         """
395            Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
396            ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
397            veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
398            comme invalide.
399            En général un validateur effectue la meme validation pour les listes partielles et les
400            listes complètes.
401         """
402         return self.verif(liste_courante)
403
404     def verif_cata(self):
405         """
406             Cette methode sert a realiser des verifications du validateur lui meme.
407             Elle est facultative et retourne 1 (valide) par defaut.
408             Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
409             parametres de definition ne sont pas corrects.
410             La raison de l'invalidite est stockee dans l'attribut cata_info.
411
412             @rtype: C{boolean}
413             @return: indicateur de validite 1 (valide) ou 0 (invalide)
414         """
415         return 1
416
417     def is_list(self):
418         """
419            Cette méthode retourne un entier qui indique si le validateur
420            permet les listes (valeur 1) ou ne les permet pas (valeur 0).
421            Par défaut, un validateur n'autorise que des scalaires.
422         """
423         return 0
424
425     def has_into(self):
426         """
427            Cette méthode retourne un entier qui indique si le validateur
428            propose une liste de choix (valeur 1) ou n'en propose pas.
429            Par défaut, un validateur n'en propose pas.
430         """
431         return 0
432
433     def get_into(self, liste_courante=None, into_courant=None):
434         """
435            Cette méthode retourne la liste de choix proposée par le validateur.
436            Si le validateur ne propose pas de liste de choix, la méthode
437            retourne None.
438            L'argument d'entrée liste_courante, s'il est différent de None, donne
439            la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
440            méthode get_into doit calculer la liste des choix en en tenant
441            compte. Par exemple, si le validateur n'autorise pas les répétitions,
442            la liste des choix retournée ne doit pas contenir les choix déjà
443            contenus dans liste_courante.
444            L'argument d'entrée into_courant, s'il est différent de None, donne
445            la liste des choix proposés par d'autres validateurs. Dans ce cas,
446            la méthode get_into doit calculer la liste des choix à retourner
447            en se limitant à cette liste initiale. Par exemple, si into_courant
448            vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
449            la méthode ne doit retourner que (3,).
450
451            La méthode get_into peut retourner une liste vide [], ce qui veut
452            dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
453            peut etre normale : l''utilisateur a utilisé tous les choix, ou
454            résulter d'une incohérence des validateurs :
455            choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
456            faire la différence entre ces deux situations.
457         """
458         return into_courant
459
460
461 class ListVal(Valid):
462
463     """
464         Cette classe sert de classe mère pour tous les validateurs qui acceptent
465         des listes.
466     """
467
468     def is_list(self):
469         return 1
470
471     def get_into(self, liste_courante=None, into_courant=None):
472         """
473            Cette méthode get_into effectue un traitement général qui consiste
474            a filtrer la liste de choix into_courant, si elle existe, en ne
475            conservant que les valeurs valides (appel de la méthode valid).
476         """
477         if into_courant is None:
478             return None
479         else:
480             liste_choix = []
481             for e in into_courant:
482                 if self.verif(e):
483                     liste_choix.append(e)
484             return liste_choix
485
486     def convert(self, valeur):
487         """
488            Méthode convert pour les validateurs de listes. Cette méthode
489            fait appel à la méthode convert_item sur chaque élément de la
490            liste.
491         """
492         if is_sequence(valeur):
493             for val in valeur:
494                 self.convert_item(val)
495             return valeur
496         else:
497             return self.convert_item(valeur)
498
499     def verif(self, valeur):
500         """
501            Méthode verif pour les validateurs de listes. Cette méthode
502            fait appel à la méthode verif_item sur chaque élément de la
503            liste. Si valeur est un paramètre, on utilise sa valeur effective
504            valeur.valeur.
505         """
506         if is_sequence(valeur):
507             for val in valeur:
508                 if not self.verif_item(val):
509                     return 0
510             return 1
511         else:
512             return self.verif_item(valeur)
513
514
515 class Compulsory(ListVal):
516     """
517         Validateur operationnel
518         Verification de la présence obligatoire d'un élément dans une liste
519     """
520     registry = {}
521
522     def __init__(self, elem=()):
523         if not is_sequence(elem):
524             elem = (elem,)
525         Valid.__init__(self, elem=elem)
526         self.elem = elem
527         self.cata_info = ""
528
529     def info(self):
530         return ufmt(_(tr(u"valeur %s obligatoire")), `self.elem`)
531
532     def default(self, valeur, elem):
533         return valeur
534
535     def verif_item(self, valeur):
536         return 1
537
538     def convert(self, valeur):
539         elem = list(self.elem)
540         for val in valeur:
541             v = self.adapt(val)
542             if v in elem:
543                 elem.remove(v)
544         if elem:
545             raise ValError(
546                 ufmt(_(tr(u"%s ne contient pas les elements obligatoires : %s ")),
547                      valeur, elem))
548         return valeur
549
550     def has_into(self):
551         return 1
552
553     def verif(self, valeur):
554         if not is_sequence(valeur):
555             liste = list(valeur)
556         else:
557             liste = valeur
558         for val in self.elem:
559             if val not in liste:
560                 return 0
561         return 1
562
563     def info_erreur_item(self):
564         return _(u"La valeur n'est pas dans la liste des choix possibles")
565
566
567 class Together(ListVal):
568     """
569         Validateur operationnel
570         si un des éléments est présent les autres doivent aussi l'être
571     """
572     registry = {}
573
574     def __init__(self, elem=()):
575         if not is_sequence(elem):
576             elem = (elem,)
577         Valid.__init__(self, elem=elem)
578         self.elem = elem
579         self.cata_info = ""
580
581     def info(self):
582         return ufmt(_(tr(u"%s present ensemble")), `self.elem`)
583
584     def default(self, valeur, elem):
585         return valeur
586
587     def verif_item(self, valeur):
588         return 1
589
590     def convert(self, valeur):
591         elem = list(self.elem)
592         for val in valeur:
593             v = self.adapt(val)
594             if v in elem: elem.remove(v)
595         if ( len(elem) == 0 ): return valeur
596         if len(elem) != len(list(self.elem)) :
597             raise ValError( ufmt(_(tr(u"%s ne contient pas les elements devant etre presents ensemble: %s ")), valeur, elem))
598         return valeur
599
600     def has_into(self):
601         return 1
602
603     def verif(self, valeur):
604         if not is_sequence(valeur):
605             liste = list(valeur)
606         else:
607             liste = valeur
608         compte = 0
609         for val in self.elem:
610             if val in liste: compte += 1
611         if ( compte == 0 ): return 1
612         if ( compte != len( list(self.elem) ) ): return 0
613         return 1
614
615     def info_erreur_item(self):
616         return _(u"La valeur n'est pas dans la liste des choix possibles")
617
618
619 class Absent(ListVal):
620     """
621         Validateur operationnel
622         si un des éléments est présent non valide
623     """
624     registry = {}
625
626     def __init__(self, elem=()):
627         if not is_sequence(elem):
628             elem = (elem,)
629         Valid.__init__(self, elem=elem)
630         self.elem = elem
631         self.cata_info = ""
632
633     def info(self):
634         return ufmt(_(tr(u"%s absent")), `self.elem`)
635
636     def default(self, valeur, elem):
637         return valeur
638
639     def verif_item(self, valeur):
640         return 1
641
642     def convert(self, valeur):
643         elem = list(self.elem)
644         for val in valeur:
645             v = self.adapt(val)
646             if v in elem:
647                 raise ValError( ufmt(_(tr(u"%s n'est pas autorise : %s ")), v, elem))
648         return valeur
649
650     def has_into(self):
651         return 1
652
653     def verif(self, valeur):
654         if not is_sequence(valeur):
655             liste = list(valeur)
656         else:
657             liste = valeur
658         for val in self.elem:
659             if val in liste: return 0
660         return 1
661
662     def info_erreur_item(self):
663         return _(u"La valeur n'est pas dans la liste des choix possibles")
664
665
666 class NoRepeat(ListVal):
667     """
668         Validateur operationnel
669         Verification d'absence de doublons dans la liste.
670     """
671     def __init__(self):
672         Valid.__init__(self)
673         self.cata_info = ""
674
675     def info(self):
676         return _(u": pas de présence de doublon dans la liste")
677
678     def info_erreur_liste(self):
679         return _(u"Les doublons ne sont pas permis")
680
681     def default(self, valeur):
682         if valeur in self.liste:
683             raise ValError(ufmt(_(tr(u"%s est un doublon")), valeur))
684         return valeur
685
686     def convert(self, valeur):
687         self.liste = []
688         for val in valeur:
689             v = self.adapt(val)
690             self.liste.append(v)
691         return valeur
692
693     def verif_item(self, valeur):
694         return 1
695
696     def verif(self, valeur):
697         if is_sequence(valeur):
698             liste = list(valeur)
699             for val in liste:
700                 if liste.count(val) != 1:
701                     return 0
702             return 1
703         else:
704             return 1
705
706     def get_into(self, liste_courante=None, into_courant=None):
707         """
708         Methode get_into spécifique pour validateur NoRepeat, on retourne
709         une liste de choix qui ne contient aucune valeur de into_courant
710         déjà contenue dans liste_courante
711         """
712         if into_courant is None:
713             liste_choix = None
714         else:
715             liste_choix = []
716             for e in into_courant:
717                 if e in liste_choix:
718                     continue
719                 if liste_courante is not None and e in liste_courante:
720                     continue
721                 liste_choix.append(e)
722         return liste_choix
723
724
725 class LongStr(ListVal):
726
727     """
728         Validateur operationnel
729         Verification de la longueur d une chaine
730     """
731
732     def __init__(self, low, high):
733         ListVal.__init__(self, low=low, high=high)
734         self.low = low
735         self.high = high
736         self.cata_info = ""
737
738     def info(self):
739         return ufmt(_(tr(u"longueur de la chaine entre %s et %s")), self.low, self.high)
740
741     def info_erreur_item(self):
742         return _(tr(u"Longueur de la chaine incorrecte"))
743
744     def convert(self, valeur):
745         for val in valeur:
746             v = self.adapt(val)
747         return valeur
748
749     def verif_item(self, valeur):
750         try:
751             self.adapt(valeur)
752             return 1
753         except:
754             return 0
755
756     def default(self, valeur, low, high):
757         if not is_str(valeur):
758             raise ValError(ufmt(_(tr(u"%s n'est pas une chaine")), repr(valeur)))
759         if valeur[0] == "'" and valeur[-1] == "'":
760             low = low + 2
761             high = high + 2
762         if len(valeur) < low or len(valeur) > high:
763             raise ValError(
764                 ufmt(_(tr(u"%s n'est pas de la bonne longueur")), repr(valeur)))
765         return valeur
766
767
768 class OnlyStr(ListVal):
769
770     """
771         Validateur operationnel
772         Valide que c'est une chaine
773     """
774
775     def __init__(self):
776         ListVal.__init__(self)
777         self.cata_info = ""
778
779     def info(self):
780         return _(u"regarde si c'est une chaine")
781
782     def info_erreur_item(self):
783         return _(u"Ce n'est pas une chaine")
784
785     def convert(self, valeur):
786         for val in valeur:
787             v = self.adapt(val)
788         return valeur
789
790     def verif_item(self, valeur):
791         try:
792             self.adapt(valeur)
793             return 1
794         except:
795             return 0
796
797     def default(self, valeur):
798         if not is_str(valeur):
799             raise ValError(ufmt(_(tr(u"%s n'est pas une chaine")), repr(valeur)))
800         return valeur
801
802
803 class OrdList(ListVal):
804
805     """
806         Validateur operationnel
807         Verification qu'une liste est croissante ou decroissante
808     """
809
810     def __init__(self, ord):
811         ListVal.__init__(self, ord=ord)
812         self.ord = ord
813         self.cata_info = ""
814
815     def info(self):
816         return ufmt(_(tr(u"liste %s")), self.ord)
817
818     def info_erreur_liste(self):
819         return ufmt(_(tr(u"La liste doit etre en ordre %s")), self.ord)
820
821     def convert(self, valeur):
822         self.val = None
823         self.liste = valeur
824         for v in valeur:
825             self.adapt(v)
826         return valeur
827
828     def default(self, valeur, ord):
829         if self.ord == 'croissant':
830             if self.val is not None and valeur < self.val:
831                 raise ValError(
832                     ufmt(_(tr(u"%s n'est pas par valeurs croissantes")), repr(self.liste)))
833         elif self.ord == 'decroissant':
834             if self.val is not None and valeur > self.val:
835                 raise ValError(
836                     ufmt(_(tr(u"%s n'est pas par valeurs decroissantes")), repr(self.liste)))
837         self.val = valeur
838         return valeur
839
840     def verif_item(self, valeur):
841         return 1
842
843     def get_into(self, liste_courante=None, into_courant=None):
844         """
845         Methode get_into spécifique pour validateur OrdList, on retourne
846         une liste de choix qui ne contient aucune valeur de into_courant
847         dont la valeur est inférieure à la dernière valeur de
848         liste_courante, si elle est différente de None.
849         """
850         if into_courant is None:
851             return None
852         elif not liste_courante:
853             return into_courant
854         else:
855             liste_choix = []
856             last_val = liste_choix[-1]
857             for e in into_courant:
858                 if self.ord == 'croissant' and e <= last_val:
859                     continue
860                 if self.ord == 'decroissant' and e >= last_val:
861                     continue
862                 liste_choix.append(e)
863             return liste_choix
864
865
866 class OrVal(Valid):
867
868     """
869         Validateur operationnel
870         Cette classe est un validateur qui controle une liste de validateurs
871         Elle verifie qu'au moins un des validateurs de la liste valide la valeur
872     """
873
874     def __init__(self, validators=()):
875         if not is_sequence(validators):
876             validators = (validators,)
877         self.validators = []
878         for validator in validators:
879             if type(validator) == types.FunctionType:
880                 self.validators.append(FunctionVal(validator))
881             else:
882                 self.validators.append(validator)
883         self.cata_info = ""
884
885     def info(self):
886         return "\n ou ".join([v.info() for v in self.validators])
887
888     def convert(self, valeur):
889         for validator in self.validators:
890             try:
891                 return validator.convert(valeur)
892             except:
893                 pass
894         raise ValError(ufmt(_(tr(u"%s n'est pas du bon type")), repr(valeur)))
895
896     def info_erreur_item(self):
897         l = []
898         for v in self.validators:
899             err = v.info_erreur_item()
900             if err != " ":
901                 l.append(err)
902         chaine = " \n ou ".join(l)
903         return chaine
904
905     def info_erreur_liste(self):
906         l = []
907         for v in self.validators:
908             err = v.info_erreur_liste()
909             if err != " ":
910                 l.append(err)
911         chaine = " \n ou ".join(l)
912         return chaine
913
914     def is_list(self):
915         """
916            Si plusieurs validateurs sont reliés par un OU
917            il suffit qu'un seul des validateurs attende une liste
918            pour qu'on considère que leur union attend une liste.
919         """
920         for validator in self.validators:
921             v = validator.is_list()
922             if v:
923                 return 1
924         return 0
925
926     def verif(self, valeur):
927         for validator in self.validators:
928             v = validator.verif(valeur)
929             if v:
930                 return 1
931         return 0
932
933     def verif_item(self, valeur):
934         for validator in self.validators:
935             v = validator.verif_item(valeur)
936             if v:
937                 return 1
938         return 0
939
940     def verif_cata(self):
941         infos = []
942         for validator in self.validators:
943             v = validator.verif_cata()
944             if not v:
945                 infos.append(validator.cata_info)
946         if infos:
947             self.cata_info = "\n".join(infos)
948             return 0
949         self.cata_info = ""
950         return 1
951
952     def has_into(self):
953         """
954         Dans le cas ou plusieurs validateurs sont reliés par un OU
955         il faut que tous les validateurs proposent un choix pour
956         qu'on considère que leur union propose un choix.
957         Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
958         En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
959         """
960         for validator in self.validators:
961             v = validator.has_into()
962             if not v:
963                 return 0
964         return 1
965
966     def get_into(self, liste_courante=None, into_courant=None):
967         """
968         Dans le cas ou plusieurs validateurs sont reliés par un OU
969         tous les validateurs doivent proposer un choix pour
970         qu'on considère que leur union propose un choix. Tous les choix
971         proposés par les validateurs sont réunis (opérateur d'union).
972         Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
973         En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
974         choix (1,2,3,4,5,6)
975         """
976         validator_into = []
977         for validator in self.validators:
978             v_into = validator.get_into(liste_courante, into_courant)
979             if v_into is None:
980                 return v_into
981             validator_into.extend(v_into)
982         return validator_into
983
984     def valide_liste_partielle(self, liste_courante=None):
985         """
986          Méthode de validation de liste partielle pour le validateur Or.
987          Si un des validateurs gérés par le validateur Or considère la
988          liste comme valide, le validateur Or la considère comme valide.
989         """
990         for validator in self.validators:
991             v = validator.valide_liste_partielle(liste_courante)
992             if v:
993                 return 1
994         return 0
995
996
997 class AndVal(Valid):
998
999     """
1000         Validateur operationnel
1001         Cette classe est un validateur qui controle une liste de validateurs
1002         Elle verifie que tous les validateurs de la liste valident la valeur
1003     """
1004
1005     def __init__(self, validators=()):
1006         if not is_sequence(validators):
1007             validators = (validators,)
1008         self.validators = []
1009         for validator in validators:
1010             if type(validator) == types.FunctionType:
1011                 self.validators.append(FunctionVal(validator))
1012             else:
1013                 self.validators.append(validator)
1014             if hasattr(validator, 'fonctions'):
1015                 for fonction in validator.fonctions:
1016                     f = getattr(validator, fonction)
1017                     setattr(self, fonction, f)
1018         self.cata_info = ""
1019
1020     def info(self):
1021         return "\n et ".join([v.info() for v in self.validators])
1022
1023     def convert(self, valeur):
1024         for validator in self.validators:
1025             valeur = validator.convert(valeur)
1026         return valeur
1027
1028     def info_erreur_item(self):
1029         chaine = ""
1030         a = 1
1031         for v in self.validators:
1032             if v.info_erreur_item() != " ":
1033                 if a == 1:
1034                     chaine = v.info_erreur_item()
1035                     a = 0
1036                 else:
1037                     chaine = chaine + " \n et " + v.info_erreur_item()
1038         return chaine
1039
1040     def info_erreur_liste(self):
1041         a = 1
1042         for v in self.validators:
1043             if v.info_erreur_liste() != " ":
1044                 if a == 1:
1045                     chaine = v.info_erreur_liste()
1046                     a = 0
1047                 else:
1048                     chaine = chaine + " \n et " + v.info_erreur_liste()
1049         return chaine
1050
1051     def verif(self, valeur):
1052         for validator in self.validators:
1053             v = validator.verif(valeur)
1054             if not v:
1055                 self.local_info = validator.info()
1056                 return 0
1057         return 1
1058
1059     def verif_item(self, valeur):
1060         for validator in self.validators:
1061             v = validator.verif_item(valeur)
1062             if not v:
1063                 # L'info n'est probablement pas la meme que pour verif ???
1064                 self.local_info = validator.info()
1065                 return 0
1066         return 1
1067
1068     def verif_cata(self):
1069         infos = []
1070         for validator in self.validators:
1071             v = validator.verif_cata()
1072             if not v:
1073                 infos.append(validator.cata_info)
1074         if infos:
1075             self.cata_info = "\n".join(infos)
1076             return 0
1077         self.cata_info = ""
1078         return 1
1079
1080     def valide_liste_partielle(self, liste_courante=None):
1081         """
1082          Méthode de validation de liste partielle pour le validateur And.
1083          Tous les validateurs gérés par le validateur And doivent considérer
1084          la liste comme valide, pour que le validateur And la considère
1085          comme valide.
1086         """
1087         for validator in self.validators:
1088             v = validator.valide_liste_partielle(liste_courante)
1089             if not v:
1090                 return 0
1091         return 1
1092
1093     def is_list(self):
1094         """
1095         Si plusieurs validateurs sont reliés par un ET
1096         il faut que tous les validateurs attendent une liste
1097         pour qu'on considère que leur intersection attende une liste.
1098         Exemple Range(2,5) ET Card(1) n'attend pas une liste
1099         Range(2,5) ET Pair attend une liste
1100         """
1101         for validator in self.validators:
1102             v = validator.is_list()
1103             if v == 0:
1104                 return 0
1105         return 1
1106
1107     def has_into(self):
1108         """
1109         Dans le cas ou plusieurs validateurs sont reliés par un ET
1110         il suffit qu'un seul validateur propose un choix pour
1111         qu'on considère que leur intersection propose un choix.
1112         Exemple : Enum(1,2,3) ET entier pair, propose un choix
1113         En revanche, entier pair ET superieur à 10 ne propose pas de choix
1114         """
1115         for validator in self.validators:
1116             v = validator.has_into()
1117             if v:
1118                 return 1
1119         return 0
1120
1121     def get_into(self, liste_courante=None, into_courant=None):
1122         """
1123         Dans le cas ou plusieurs validateurs sont reliés par un ET
1124         il suffit qu'un seul validateur propose un choix pour
1125         qu'on considère que leur intersection propose un choix. Tous les
1126         choix proposés par les validateurs sont croisés (opérateur
1127         d'intersection)
1128         Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
1129         En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
1130         """
1131         for validator in self.validators:
1132             into_courant = validator.get_into(liste_courante, into_courant)
1133             if into_courant in ([], None):
1134                 break
1135         return into_courant
1136
1137
1138 def do_liste(validators):
1139     """
1140        Convertit une arborescence de validateurs en OrVal ou AndVal
1141        validators est une liste de validateurs ou de listes ou de tuples
1142     """
1143     valids = []
1144     for validator in validators:
1145         if type(validator) == types.FunctionType:
1146             valids.append(FunctionVal(validator))
1147         elif type(validator) is tuple:
1148             valids.append(OrVal(do_liste(validator)))
1149         elif type(validator) is list:
1150             valids.append(AndVal(do_liste(validator)))
1151         else:
1152             valids.append(validator)
1153     return valids
1154
1155
1156 def validatorFactory(validator):
1157     if type(validator) == types.FunctionType:
1158         return FunctionVal(validator)
1159     elif type(validator) is tuple:
1160         return OrVal(do_liste(validator))
1161     elif type(validator) is list:
1162         return AndVal(do_liste(validator))
1163     else:
1164         return validator
1165
1166 # Ci-dessous : exemples de validateur (peu testés)
1167
1168
1169 class RangeVal(ListVal):
1170
1171     """
1172         Exemple de classe validateur : verification qu'une valeur
1173         est dans un intervalle.
1174         Pour une liste on verifie que tous les elements sont
1175         dans l'intervalle
1176         Susceptible de remplacer les attributs "vale_min" "vale_max"
1177         dans les catalogues
1178     """
1179
1180     def __init__(self, low, high):
1181         self.low = low
1182         self.high = high
1183         self.cata_info = ufmt(_(tr(u"%s doit etre inferieur a %s")), low, high)
1184
1185     def info(self):
1186         return ufmt(_(tr(u"valeur dans l'intervalle %s , %s")), self.low, self.high)
1187
1188     def convert_item(self, valeur):
1189         if valeur > self.low and valeur < self.high:
1190             return valeur
1191         raise ValError(ufmt(_(tr(u"%s devrait etre comprise entre %s et %s")),
1192                             valeur, self.low, self.high))
1193
1194     def verif_item(self, valeur):
1195         return valeur > self.low and valeur < self.high
1196
1197     def info_erreur_item(self):
1198         return ufmt(_(tr(u"La valeur doit etre comprise entre %s et %s")), self.low, self.high)
1199
1200     def verif_cata(self):
1201         if self.low > self.high:
1202             return 0
1203         return 1
1204
1205
1206 class CardVal(Valid):
1207
1208     """
1209         Exemple de classe validateur : verification qu'une liste est
1210         d'une longueur superieur a un minimum (min) et inferieure
1211         a un maximum (max).
1212         Susceptible de remplacer les attributs "min" "max" dans les
1213         catalogues
1214     """
1215
1216     def __init__(self, min='**', max='**'):
1217         self.min = min
1218         self.max = max
1219         self.cata_info = ufmt(_(tr(u"%s doit etre inferieur a %s")), min, max)
1220
1221     def info(self):
1222         return ufmt(_(tr(u"longueur de liste comprise entre  %s et %s")), self.min, self.max)
1223
1224     def info_erreur_liste(self):
1225         return ufmt(
1226             _(tr(u"Le cardinal de la liste doit etre compris entre %s et %s")),
1227             self.min, self.max)
1228
1229     def is_list(self):
1230         return self.max == '**' or self.max > 1
1231
1232     def get_into(self, liste_courante=None, into_courant=None):
1233         if into_courant is None:
1234             return None
1235         elif liste_courante is None:
1236             return into_courant
1237         elif self.max == '**':
1238             return into_courant
1239         elif len(liste_courante) < self.max:
1240             return into_courant
1241         else:
1242             return []
1243
1244     def convert(self, valeur):
1245         if is_sequence(valeur):
1246             l = len(valeur)
1247         elif valeur is None:
1248             l = 0
1249         else:
1250             l = 1
1251         if self.max != '**' and l > self.max:
1252             raise ValError(
1253                 ufmt(_(tr(u"%s devrait etre de longueur inferieure a %s")), valeur, self.max))
1254         if self.min != '**' and l < self.min:
1255             raise ValError(
1256                 ufmt(_(tr(u"%s devrait etre de longueur superieure a %s")), valeur, self.min))
1257         return valeur
1258
1259     def verif_item(self, valeur):
1260         return 1
1261
1262     def verif(self, valeur):
1263         if is_sequence(valeur):
1264             if self.max != '**' and len(valeur) > self.max:
1265                 return 0
1266             if self.min != '**' and len(valeur) < self.min:
1267                 return 0
1268             return 1
1269         else:
1270             if self.max != '**' and 1 > self.max:
1271                 return 0
1272             if self.min != '**' and 1 < self.min:
1273                 return 0
1274             return 1
1275
1276     def verif_cata(self):
1277         if self.min != '**' and self.max != '**' and self.min > self.max:
1278             return 0
1279         return 1
1280
1281     def valide_liste_partielle(self, liste_courante=None):
1282         validite = 1
1283         if liste_courante != None:
1284             if len(liste_courante) > self.max:
1285                 validite = 0
1286         return validite
1287
1288
1289 class PairVal(ListVal):
1290
1291     """
1292         Exemple de classe validateur : verification qu'une valeur
1293         est paire.
1294         Pour une liste on verifie que tous les elements sont
1295         pairs
1296     """
1297
1298     def __init__(self):
1299         ListVal.__init__(self)
1300         self.cata_info = ""
1301
1302     def info(self):
1303         return _(u"valeur paire")
1304
1305     def info_erreur_item(self):
1306         return _(u"La valeur saisie doit etre paire")
1307
1308     def convert(self, valeur):
1309         for val in valeur:
1310             v = self.adapt(val)
1311             if v % 2 != 0:
1312                 raise ValError(
1313                     ufmt(_(tr(u"%s contient des valeurs non paires")), repr(valeur)))
1314         return valeur
1315
1316     def default(self, valeur):
1317         return valeur
1318
1319     def verif_item(self, valeur):
1320         if type(valeur) not in (int, long):
1321             return 0
1322         return valeur % 2 == 0
1323
1324     def verif(self, valeur):
1325         if is_sequence(valeur):
1326             for val in valeur:
1327                 if val % 2 != 0:
1328                     return 0
1329             return 1
1330         else:
1331             if valeur % 2 != 0:
1332                 return 0
1333             return 1
1334
1335
1336 class EnumVal(ListVal):
1337
1338     """
1339         Exemple de classe validateur : verification qu'une valeur
1340         est prise dans une liste de valeurs.
1341         Susceptible de remplacer l attribut "into" dans les catalogues
1342     """
1343
1344     def __init__(self, into=()):
1345         if not is_sequence(into):
1346             into = (into,)
1347         self.into = into
1348         self.cata_info = ""
1349
1350     def info(self):
1351         return "valeur dans %s" % `self.into`
1352
1353     def convert_item(self, valeur):
1354         if valeur in self.into:
1355             return valeur
1356         raise ValError(
1357             ufmt(_(tr(u"%s contient des valeurs hors des choix possibles: %s ")),
1358                  valeur, self.into))
1359
1360     def verif_item(self, valeur):
1361         if valeur not in self.into:
1362             return 0
1363         return 1
1364
1365     def has_into(self):
1366         return 1
1367
1368     def get_into(self, liste_courante=None, into_courant=None):
1369         if into_courant is None:
1370             liste_choix = list(self.into)
1371         else:
1372             liste_choix = []
1373             for e in into_courant:
1374                 if e in self.into:
1375                     liste_choix.append(e)
1376         return liste_choix
1377
1378     def info_erreur_item(self):
1379         return _(u"La valeur n'est pas dans la liste des choix possibles")
1380
1381
1382 def ImpairVal(valeur):
1383     """
1384           Exemple de validateur
1385         Cette fonction est un validateur. Elle verifie que la valeur passee
1386         est bien un nombre impair.
1387     """
1388     if is_sequence(valeur):
1389         for val in valeur:
1390             if val % 2 != 1:
1391                 return 0
1392         return 1
1393     else:
1394         if valeur % 2 != 1:
1395             return 0
1396         return 1
1397
1398 ImpairVal.info = "valeur impaire"
1399
1400
1401 class F1Val(Valid):
1402
1403     """
1404         Exemple de validateur
1405         Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1406         que la somme des cles A et B vaut une valeur donnee
1407         en parametre du validateur
1408     """
1409
1410     def __init__(self, somme=10):
1411         self.somme = somme
1412         self.cata_info = ""
1413
1414     def info(self):
1415         return ufmt(_(tr(u"valeur %s pour la somme des cles A et B ")), self.somme)
1416
1417     def verif(self, valeur):
1418         if is_sequence(valeur):
1419             for val in valeur:
1420                 if not val.has_key("A"):
1421                     return 0
1422                 if not val.has_key("B"):
1423                     return 0
1424                 if val["A"] + val["B"] != self.somme:
1425                     return 0
1426             return 1
1427         else:
1428             if not valeur.has_key("A"):
1429                 return 0
1430             if not valeur.has_key("B"):
1431                 return 0
1432             if valeur["A"] + valeur["B"] != self.somme:
1433                 return 0
1434             return 1
1435
1436
1437 class FunctionVal(Valid):
1438
1439     """
1440         Exemple de validateur
1441         Cette classe est un validateur qui est initialise avec une fonction
1442     """
1443
1444     def __init__(self, function):
1445         self.function = function
1446
1447     def info(self):
1448         return self.function.info
1449
1450     def verif(self, valeur):
1451         return self.function(valeur)
1452
1453     def verif_item(self, valeur):
1454         return self.function(valeur)
1455
1456     def convert(self, valeur):
1457         return valeur
1458
1459 # MC ca ne devrait plus servir !
1460 CoercableFuncs = {types.IntType:     int,
1461                   types.LongType:    long,
1462                   types.FloatType:   float,
1463                   types.ComplexType: complex,
1464                   types.UnicodeType: unicode}
1465
1466
1467 class TypeVal(ListVal):
1468
1469     """
1470         Exemple de validateur
1471         Cette classe est un validateur qui controle qu'une valeur
1472         est bien du type Python attendu.
1473         Pour une liste on verifie que tous les elements sont du bon type.
1474         Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1475         alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1476     """
1477
1478     def __init__(self, aType):
1479         # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1480         # type(1) == int;type(0.2)==float;etc.
1481         if type(aType) != types.TypeType:
1482             aType = type(aType)
1483         self.aType = aType
1484         try:
1485             self.coerce = CoercableFuncs[aType]
1486         except:
1487             self.coerce = self.identity
1488
1489     def info(self):
1490         return ufmt(_(tr(u"valeur de %s")), self.aType)
1491
1492     def identity(self, value):
1493         if type(value) == self.aType:
1494             return value
1495         raise ValError
1496
1497     def convert_item(self, valeur):
1498         return self.coerce(valeur)
1499
1500     def verif_item(self, valeur):
1501         try:
1502             self.coerce(valeur)
1503         except:
1504             return 0
1505         return 1
1506
1507
1508 class InstanceVal(ListVal):
1509
1510     """
1511         Exemple de validateur
1512         Cette classe est un validateur qui controle qu'une valeur est
1513         bien une instance (au sens Python) d'une classe
1514         Pour une liste on verifie chaque element de la liste
1515     """
1516
1517     def __init__(self, aClass):
1518         # Si aClass est une classe on la memorise dans self.aClass
1519         # sinon c'est une instance dont on memorise la classe
1520         if type(aClass) == types.InstanceType:
1521             # instance ancienne mode
1522             aClass = aClass.__class__
1523         elif type(aClass) == types.ClassType:
1524             # classe ancienne mode
1525             aClass = aClass
1526         elif type(aClass) == type:
1527             # classe nouvelle mode
1528             aClass = aClass
1529         elif isinstance(aClass, object):
1530             # instance nouvelle mode
1531             aClass = type(aClass)
1532         else:
1533             raise ValError(_(u"type non supporté"))
1534
1535         self.aClass = aClass
1536
1537     def info(self):
1538         return ufmt(_(tr(u"valeur d'instance de %s")), self.aClass.__name__)
1539
1540     def verif_item(self, valeur):
1541         if not isinstance(valeur, self.aClass):
1542             return 0
1543         return 1
1544
1545
1546 class VerifTypeTuple(Valid, ListVal):
1547
1548     def __init__(self, typeDesTuples):
1549         self.typeDesTuples = typeDesTuples
1550         Valid.__init__(self)
1551         self.cata_info = ""
1552
1553     def info(self):
1554         return _(tr(u": verifie les types dans un tuple"))
1555
1556     def info_erreur_liste(self):
1557         return _(tr(u"Les types entrés ne sont pas permis"))
1558
1559     def default(self, valeur):
1560         # if valeur in self.liste : raise ValError("%s est un doublon" %
1561         # valeur)
1562         return valeur
1563
1564     def is_list(self):
1565         return 1
1566
1567     def convert_item(self, valeur):
1568         if len(valeur) != len(self.typeDesTuples):
1569             raise ValError(
1570                 ufmt(_(tr(u"%s devrait etre de type  %s ")), valeur, self.typeDesTuples))
1571         for i in range(len(valeur)):
1572             ok = self.verifType(valeur[i], self.typeDesTuples[i])
1573             if ok != 1:
1574                 raise ValError(
1575                     ufmt(_(tr(u"%s devrait etre de type  %s ")), valeur, self.typeDesTuples))
1576         return valeur
1577
1578     def verif_item(self, valeur):
1579         try:
1580             if len(valeur) != len(self.typeDesTuples):
1581                 return 0
1582             for i in range(len(valeur)):
1583                 ok = self.verifType(valeur[i], self.typeDesTuples[i])
1584                 if ok != 1:
1585                     return 0
1586         except:
1587             return 0
1588         return 1
1589
1590     def verifType(self, valeur, type_permis):
1591         if type_permis == 'R':
1592             if type(valeur) in (types.IntType, types.FloatType, types.LongType):
1593                 return 1
1594         elif type_permis == 'I':
1595             if type(valeur) in (types.IntType, types.LongType):
1596                 return 1
1597         elif type_permis == 'C':
1598             if self.is_complexe(valeur):
1599                 return 1
1600         elif type_permis == 'TXM':
1601             if type(valeur) == types.StringType:
1602                 return 1
1603         return 0
1604
1605     def verif(self, valeur):
1606         if type(valeur) in (types.ListType, types.TupleType):
1607             liste = list(valeur)
1608             for val in liste:
1609                 if self.verif_item(val) != 1:
1610                     return 0
1611             return 1
1612
1613
1614 class VerifExiste(ListVal):
1615
1616     """
1617        fonctionne avec into
1618        Met une liste à jour selon les mot clefs existant
1619        exemple si into = ("A","B","C")
1620        si au niveau N du JDC les objets "A" et "C" existe
1621        alors la liste des into deviendra ( "A","C")
1622
1623        niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1624        niveauVerif est defini par rapport au Noeud :
1625        exemple niveauVerif = 1 : on verifie les freres
1626                niveauVerif = 2 : on verifie les oncles..
1627     """
1628
1629     def __init__(self, niveauVerif):
1630         ListVal.__init__(self)
1631         self.niveauVerif = niveauVerif
1632         self.MCSimp = None
1633         self.listeDesFreres = ()
1634         self.fonctions = ('verifie_liste', 'set_MCSimp')
1635
1636     def is_list(self):
1637         return 1
1638
1639     def verifie_liste(self, liste):
1640         self.set_MCSimp(self.MCSimp)
1641         for item in liste:
1642             if not(item in self.listeDesFreres):
1643                 return 0
1644         return 1
1645
1646     def verif_item(self, valeur):
1647         self.set_MCSimp(self.MCSimp)
1648         if valeur in self.listeDesFreres:
1649             return 1
1650         return 0
1651
1652     def set_MCSimp(self, MCSimp):
1653         self.MCSimp = MCSimp
1654         k = self.niveauVerif
1655         mc = MCSimp
1656         while (k != 0):
1657             parent = mc.parent
1658             mc = parent
1659             k = k - 1
1660         # on met la liste à jour
1661         parent.forceRecalcul = self.niveauVerif
1662         self.listeDesFreres = parent.liste_mc_presents()
1663
1664     def convert_item(self, valeur):
1665         if valeur in self.listeDesFreres:
1666             return valeur
1667         raise ValError(
1668             ufmt(_(tr(u"%s n'est pas dans %s")), valeur, self.listeDesFreres))
1669
1670
1671 class RegExpVal(ListVal):
1672
1673     """
1674     Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1675     """
1676
1677     errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1678
1679     def __init__(self, pattern):
1680         self.pattern = pattern
1681         self.compiled_regexp = re.compile(pattern)
1682
1683     def info(self):
1684         return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
1685
1686     def verif_item(self, valeur):
1687         if self.compiled_regexp.match(valeur):
1688             return 1
1689         else:
1690             return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1691
1692     def convert_item(self, valeur):
1693         if self.compiled_regexp.match(valeur):
1694             return valeur
1695         else:
1696             raise ValError(self.errormsg %
1697                            {"value": valeur, "pattern": self.pattern})
1698
1699
1700 class FileExtVal(RegExpVal):
1701
1702     """
1703     Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1704     """
1705
1706     def __init__(self, ext):
1707         self.ext = ext
1708         self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1709             "ext": ext}
1710         #RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
1711         #PNPN Modif pour Adao
1712         #RegExpVal.__init__(self, "^[\S]+\.%s$" % self.ext
1713         RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
1714
1715
1716     def info(self):
1717         return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext