Salome HOME
sauvegarde du 28/07
[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 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         chaine=""
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(": verifie les types dans un tuple"))
1555
1556     def info_erreur_liste(self):
1557         return _(tr("Les types entres 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         elif isinstance(valeur, type_permis):
1604                 return 1
1605         return 0
1606
1607     def verif(self, valeur):
1608         if type(valeur) in (types.ListType, types.TupleType):
1609             liste = list(valeur)
1610             for val in liste:
1611                 if self.verif_item(val) != 1:
1612                     return 0
1613             return 1
1614
1615
1616 class VerifExiste(ListVal):
1617
1618     """
1619        fonctionne avec into
1620        Met une liste à jour selon les mot clefs existant
1621        exemple si into = ("A","B","C")
1622        si au niveau N du JDC les objets "A" et "C" existe
1623        alors la liste des into deviendra ( "A","C")
1624
1625        niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1626        niveauVerif est defini par rapport au Noeud :
1627        exemple niveauVerif = 1 : on verifie les freres
1628                niveauVerif = 2 : on verifie les oncles..
1629     """
1630
1631     def __init__(self, niveauVerif):
1632         ListVal.__init__(self)
1633         self.niveauVerif = niveauVerif
1634         self.MCSimp = None
1635         self.listeDesFreres = ()
1636         self.fonctions = ('verifie_liste', 'set_MCSimp')
1637
1638     def is_list(self):
1639         return 1
1640
1641     def verifie_liste(self, liste):
1642         self.set_MCSimp(self.MCSimp)
1643         for item in liste:
1644             if not(item in self.listeDesFreres):
1645                 return 0
1646         return 1
1647
1648     def verif_item(self, valeur):
1649         self.set_MCSimp(self.MCSimp)
1650         if valeur in self.listeDesFreres:
1651             return 1
1652         return 0
1653
1654     def set_MCSimp(self, MCSimp):
1655         self.MCSimp = MCSimp
1656         k = self.niveauVerif
1657         mc = MCSimp
1658         while (k != 0):
1659             parent = mc.parent
1660             mc = parent
1661             k = k - 1
1662         # on met la liste à jour
1663         parent.forceRecalcul = self.niveauVerif
1664         self.listeDesFreres = parent.liste_mc_presents()
1665
1666     def convert_item(self, valeur):
1667         if valeur in self.listeDesFreres:
1668             return valeur
1669         raise ValError(
1670             ufmt(_(tr(u"%s n'est pas dans %s")), valeur, self.listeDesFreres))
1671
1672
1673 class RegExpVal(ListVal):
1674
1675     """
1676     Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1677     """
1678
1679     errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1680
1681     def __init__(self, pattern):
1682         self.pattern = pattern
1683         self.compiled_regexp = re.compile(pattern)
1684
1685     def info(self):
1686         return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
1687
1688     def verif_item(self, valeur):
1689         if self.compiled_regexp.match(valeur):
1690             return 1
1691         else:
1692             return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1693
1694     def convert_item(self, valeur):
1695         if self.compiled_regexp.match(valeur):
1696             return valeur
1697         else:
1698             raise ValError(self.errormsg %
1699                            {"value": valeur, "pattern": self.pattern})
1700
1701
1702 class FileExtVal(RegExpVal):
1703
1704     """
1705     Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1706     """
1707
1708     def __init__(self, ext):
1709         self.ext = ext
1710         self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
1711             "ext": ext}
1712         #RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
1713         #PNPN Modif pour Adao
1714         #RegExpVal.__init__(self, "^[\S]+\.%s$" % self.ext
1715         RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
1716
1717
1718     def info(self):
1719         return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext
1720
1721 class CreeMotClef:
1722     def __init__(self,MotClef ):
1723         self.MotClef=MotClef
1724         self.MCSimp=None
1725          
1726     def convert(self, lval):
1727         print "dans convert"
1728         try : valeur=lval[0]
1729         except  : return lval
1730
1731         parent= self.MCSimp.parent
1732         if hasattr(parent, 'inhibeValidator') and parent.inhibeValidator: return lval
1733
1734
1735         if parent.get_child(self.MotClef) == None : longueur=0
1736         else : longueur=len(parent.get_child(self.MotClef))
1737
1738         pos=parent.get_index_child(self.MCSimp.nom)+1
1739         while longueur < valeur : 
1740            parent.inhibeValidator=1
1741            parent.addentite(self.MotClef,pos)
1742            pos=pos+1
1743            parent.inhibeValidator=0
1744            longueur=len(parent.get_child(self.MotClef))
1745
1746         if longueur > valeur : 
1747            parent.inhibeValide=1
1748            parentObj=parent.get_child(self.MotClef)
1749            obj=parent.get_child(self.MotClef)[-1]
1750            parentObj.suppentite(obj)
1751            longueur=len(parent.get_child(self.MotClef))
1752            parent.inhibeValide=0
1753         return lval
1754
1755     def info(self):
1756         return "Cree le bon nombre de Mot %s"  % self.MotClef
1757
1758     def verif_item(self, valeur):
1759         return 1
1760
1761     def set_MCSimp(self, MCSimp):
1762         #print "dans set_MCSimp"
1763         self.MCSimp=MCSimp