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