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