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