Salome HOME
CCAR: ajout des fichiers macros
[tools/eficas.git] / Noyau / N_VALIDATOR.py
1 # -*- coding: utf-8 -*-
2 #@ MODIF N_VALIDATOR Noyau  DATE 04/02/2004   AUTEUR CAMBIER S.CAMBIER 
3 #            CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2003  EDF R&D                  WWW.CODE-ASTER.ORG
6 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY  
7 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY  
8 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR     
9 # (AT YOUR OPTION) ANY LATER VERSION.                                                  
10 #                                                                       
11 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT   
12 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF            
13 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU      
14 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.                              
15 #                                                                       
16 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE     
17 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,         
18 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.        
19 # ======================================================================
20 """
21    Ce module contient toutes les classes necessaires pour
22    implanter le concept de validateur dans Accas
23 """
24 import types,exceptions
25
26 class ValError ( exceptions.Exception ):
27       pass
28
29 class Valid:
30    """
31         Cette classe est la classe mere des validateurs Accas
32         Elle doit etre derivee 
33         Elle presente la signature des methodes indispensables pour son bon 
34         fonctionnement et dans certains cas leur comportement par défaut.
35
36         @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
37         @type cata_info: C{string}
38    """
39    def __init__(self,*tup,**args):
40        """ 
41            Cette methode sert a initialiser les attributs du validateur 
42        """
43        self.cata_info=""
44        raise "Must be implemented"
45
46    def info(self):
47        """
48           Cette methode retourne une chaine de caractères informative sur
49           la validation demandée par le validateur. Elle est utilisée
50           pour produire le compte-rendu de validité du mot clé associé.
51        """
52        return "valeur valide" 
53
54    def aide(self):
55        """
56           Cette methode retourne une chaine de caractère qui permet 
57           de construire un message d'aide en ligne.
58           En général, le message retourné est le meme que celui retourné par la
59           méthode info.
60        """
61        return self.info()
62
63    def info_erreur_item(self):
64        """
65           Cette méthode permet d'avoir un message d'erreur pour un item
66           dans une liste dans le cas ou le validateur fait des vérifications
67           sur les items d'une liste. Si le validateur fait seulement des
68           vérifications sur la liste elle meme et non sur ses items, la méthode
69           doit retourner une chaine vide.
70        """
71        return " "
72
73    def info_erreur_liste(self):
74        """
75           Cette méthode a un comportement complémentaire de celui de
76           info_erreur_item. Elle retourne un message d'erreur lié uniquement
77           aux vérifications sur la liste elle meme et pas sur ses items.
78           Dans le cas où le validateur ne fait pas de vérification sur des
79           listes, elle retourne une chaine vide
80        """
81        return " "
82
83    def verif(self,valeur):
84        """
85            Cette methode sert a verifier si la valeur passee en argument est consideree
86            comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
87            (valide) sinon 0 (invalide).
88
89            @type valeur: tout type python
90            @param valeur: valeur du mot cle a valider
91            @rtype: C{boolean}
92            @return: indicateur de validite 1 (valide) ou 0 (invalide)
93        """
94        raise "Must be implemented"
95    
96    def verif_item(self,valeur):
97        """
98           La methode verif du validateur effectue une validation complete de
99           la valeur. valeur peut etre un scalaire ou une liste. Le validateur
100           doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
101           methode is_list doit retourner 1).
102           La methode valid_item sert pour effectuer des validations partielles
103           de liste. Elle doit uniquement verifier la validite d'un item de
104           liste mais pas les caracteristiques de la liste.
105        """
106        return 0
107
108    def valide_liste_partielle(self,liste_courante):
109        """
110           Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
111           ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
112           veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
113           comme invalide.
114           En général un validateur effectue la meme validation pour les listes partielles et les
115           listes complètes.
116        """
117        return self.verif(liste_courante)
118
119    def verif_cata(self):
120        """
121            Cette methode sert a realiser des verifications du validateur lui meme.
122            Elle est facultative et retourne 1 (valide) par defaut.
123            Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
124            parametres de definition ne sont pas corrects.
125            La raison de l'invalidite est stockee dans l'attribut cata_info.
126
127            @rtype: C{boolean}
128            @return: indicateur de validite 1 (valide) ou 0 (invalide)
129        """
130        return 1
131
132    def is_list(self):
133        """
134           Cette méthode retourne un entier qui indique si le validateur
135           permet les listes (valeur 1) ou ne les permet pas (valeur 0).
136           Par défaut, un validateur n'autorise que des scalaires.
137        """
138        return 0
139
140    def has_into(self):
141        """
142           Cette méthode retourne un entier qui indique si le validateur
143           propose une liste de choix (valeur 1) ou n'en propose pas.
144           Par défaut, un validateur n'en propose pas.
145        """
146        return 0
147
148    def get_into(self,liste_courante=None,into_courant=None):
149        """
150           Cette méthode retourne la liste de choix proposée par le validateur.
151           Si le validateur ne propose pas de liste de choix, la méthode
152           retourne None.
153           L'argument d'entrée liste_courante, s'il est différent de None, donne
154           la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
155           méthode get_into doit calculer la liste des choix en en tenant
156           compte. Par exemple, si le validateur n'autorise pas les répétitions,
157           la liste des choix retournée ne doit pas contenir les choix déjà
158           contenus dans liste_courante.
159           L'argument d'entrée into_courant, s'il est différent de None, donne
160           la liste des choix proposés par d'autres validateurs. Dans ce cas,
161           la méthode get_into doit calculer la liste des choix à retourner
162           en se limitant à cette liste initiale. Par exemple, si into_courant
163           vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
164           la méthode ne doit retourner que (3,).
165
166           La méthode get_into peut retourner une liste vide [], ce qui veut
167           dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
168           peut etre normale : l''utilisateur a utilisé tous les choix, ou
169           résulter d'une incohérence des validateurs :
170           choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
171           faire la différence entre ces deux situations.
172        """
173        return into_courant
174
175    def is_eval(self,valeur):
176        """
177            Cette méthode indique si valeur est un objet de type EVAL ou autre
178            que l'on ne cherchera pas à evaluer et qui doit etre considere
179            comme toujours valide. Si c'est un objet de ce type elle retourne
180            la valeur 1 sinon la valeur 0
181        """
182        return type(valeur) == types.InstanceType and valeur.__class__.__name__ in ('EVAL',
183                     'entier','reel','chaine', 'complexe','liste','PARAMETRE_EVAL')
184
185    def is_param(self,valeur):
186        """
187            Cette méthode indique si valeur est un objet de type PARAMETRE
188            dont on cherchera à evaluer la valeur (valeur.valeur)
189        """
190        return type(valeur) == types.InstanceType and valeur.__class__.__name__ in ('PARAMETRE',)
191
192    def is_unknown(self,valeur):
193        """
194            Cette méthode indique si valeur est un objet de type inconnu
195            c'est à dire ni de type EVAL ni de type PARAMETRE
196        """
197        return type(valeur) == types.InstanceType and valeur.__class__.__name__ not in ('EVAL',
198                     'entier','reel','chaine', 'complexe','liste','PARAMETRE_EVAL','PARAMETRE')
199
200 class ListVal(Valid):
201    """
202        Cette classe sert de classe mère pour tous les validateurs qui acceptent
203        des listes.
204    """
205    def is_list(self):
206        return 1
207
208    def get_into(self,liste_courante=None,into_courant=None):
209        """
210           Cette méthode get_into effectue un traitement général qui consiste
211           a filtrer la liste de choix into_courant, si elle existe, en ne
212           conservant que les valeurs valides (appel de la méthode valid).
213        """
214        if into_courant is None:
215           return None
216        else:
217           liste_choix=[]
218           for e in into_courant:
219               if self.verif(e):
220                  liste_choix.append(e)
221           return liste_choix
222
223    def verif(self,valeur):
224        """
225           Méthode verif pour les validateurs de listes. Cette méthode
226           fait appel à la méthode verif_item sur chaque élément de la 
227           liste. Si valeur est un paramètre, on utilise sa valeur effective
228           valeur.valeur.
229        """
230        if self.is_param(valeur):
231           valeur=valeur.valeur
232        if type(valeur) in (types.ListType,types.TupleType):
233           for val in valeur:
234               if not self.verif_item(val):
235                  return 0
236           return 1
237        else:
238           return self.verif_item(valeur)
239
240 class RangeVal(ListVal):
241       """
242           Exemple de classe validateur : verification qu'une valeur
243           est dans un intervalle.
244           Pour une liste on verifie que tous les elements sont 
245           dans l'intervalle
246           Susceptible de remplacer les attributs "vale_min" "vale_max"
247           dans les catalogues
248       """
249       def __init__(self,low,high):
250           self.low=low
251           self.high=high
252           self.cata_info="%s doit etre inferieur a %s" %(low,high)
253
254       def info(self):
255           return "valeur dans l'intervalle %s , %s" %(self.low,self.high)
256
257       def verif_item(self,valeur):
258           return valeur > self.low and valeur < self.high
259
260       def info_erreur_item(self) :
261           return "La valeur doit etre comprise entre %s et %s" % (self.low,
262                                                                   self.high)
263
264       def verif_cata(self):
265           if self.low > self.high : return 0
266           return 1
267
268 class CardVal(Valid):
269       """
270           Exemple de classe validateur : verification qu'une liste est
271           d'une longueur superieur a un minimum (min) et inferieure
272           a un maximum (max).
273           Susceptible de remplacer les attributs "min" "max" dans les
274           catalogues
275       """
276       def __init__(self,min='**',max='**'):
277           self.min=min
278           self.max=max  
279           self.cata_info="%s doit etre inferieur a %s" % (min,max)
280
281       def info(self):
282           return "longueur de liste comprise entre  %s et %s" % (self.min,self.max)
283
284       def info_erreur_liste(self):
285           return "Le cardinal de la liste doit etre compris entre %s et %s" % (self.min,self.max)
286
287       def is_list(self):
288           return self.max == '**' or self.max > 1
289
290       def get_into(self,liste_courante=None,into_courant=None):
291           if into_courant is None:
292              return None
293           elif liste_courante is None:
294              return into_courant
295           elif self.max == '**':
296              return into_courant
297           elif len(liste_courante) < self.max:
298              return into_courant
299           else:
300              return []
301
302       def verif_item(self,valeur):
303           return 1
304
305       def verif(self,valeur):
306           if type(valeur) in (types.ListType,types.TupleType):
307              if self.max != '**' and len(valeur) > self.max:return 0
308              if self.min != '**' and len(valeur) < self.min:return 0
309              return 1
310           else:
311              if self.max != '**' and 1 > self.max:return 0
312              if self.min != '**' and 1 < self.min:return 0
313              return 1
314
315       def verif_cata(self):
316           if self.min != '**' and self.max != '**' and self.min > self.max : return 0
317           return 1
318
319       def valide_liste_partielle(self,liste_courante=None):
320           validite=1
321           if liste_courante != None :
322              if len(liste_courante) > self.max :
323                 validite=0
324           return validite
325
326 class PairVal(ListVal):
327       """
328           Exemple de classe validateur : verification qu'une valeur
329           est paire.
330           Pour une liste on verifie que tous les elements sont
331           pairs
332       """
333       def __init__(self):
334           self.cata_info=""
335
336       def info(self):
337           return "valeur paire"
338
339       def info_erreur_item(self):
340           return "La valeur saisie doit etre paire"
341
342       def verif_item(self,valeur):
343           if type(valeur) == types.InstanceType:
344              if self.is_eval(valeur):
345                 return 1
346              elif self.is_param(valeur):
347                 valeur=valeur.valeur
348              else:
349                 return 0
350           return valeur % 2 == 0
351
352       def verif(self,valeur):
353           if type(valeur) in (types.ListType,types.TupleType):
354              for val in valeur:
355                 if val % 2 != 0:return 0
356              return 1
357           else:
358              if valeur % 2 != 0:return 0
359              return 1
360
361 class EnumVal(ListVal):
362       """
363           Exemple de classe validateur : verification qu'une valeur
364           est prise dans une liste de valeurs.
365           Susceptible de remplacer l attribut "into" dans les catalogues
366       """
367       def __init__(self,into=()):
368           if type(into) not in (types.ListType,types.TupleType): into=(into,)
369           self.into=into
370           self.cata_info=""
371
372       def info(self):
373           return "valeur dans %s" % `self.into`
374
375       def verif_item(self,valeur):
376           if valeur not in self.into:return 0
377           return 1
378
379       def has_into(self):
380           return 1
381
382       def get_into(self,liste_courante=None,into_courant=None):
383           if into_courant is None:
384              liste_choix= list(self.into)
385           else:
386              liste_choix=[]
387              for e in into_courant:
388                  if e in self.into:
389                     liste_choix.append(e)
390           return liste_choix
391
392       def info_erreur_item(self):
393           return "La valeur n'est pas dans la liste des choix possibles"
394
395 class NoRepeat(ListVal):
396       """
397           Verification d'absence de doublons dans la liste.
398       """
399       def __init__(self):
400           self.cata_info=""
401
402       def info(self):
403           return ": pas de présence de doublon dans la liste"
404
405       def info_erreur_liste(self):
406           return "Les doublons ne sont pas permis"
407
408       def verif_item(self,valeur):
409           return 1
410
411       def verif(self,valeur):
412           if type(valeur) in (types.ListType,types.TupleType):
413              liste=list(valeur)
414              for val in liste:
415                 if liste.count(val)!=1 : return 0
416              return 1
417           else:
418              return 1
419
420       def get_into(self,liste_courante=None,into_courant=None):
421           """
422           Methode get_into spécifique pour validateur NoRepeat, on retourne
423           une liste de choix qui ne contient aucune valeur de into_courant
424           déjà contenue dans liste_courante
425           """
426           if into_courant is None:
427              liste_choix=None
428           else:
429              liste_choix=[]
430              for e in into_courant:
431                  if e in liste_choix: continue
432                  if liste_courante is not None and e in liste_courante: continue
433                  liste_choix.append(e)
434           return liste_choix
435
436 class LongStr(ListVal):
437       """
438           Verification de la longueur d une chaine
439       """
440       def __init__(self,low,high):
441           self.low=low
442           self.high=high
443           self.cata_info=""
444
445       def info(self):
446           return "longueur de la chaine entre %s et %s" %(self.low,self.high)
447
448       def info_erreur_item(self):
449           return "Longueur de la chaine incorrecte"
450
451       def verif_item(self,valeur):
452           low=self.low
453           high=self.high
454           if valeur[0]=="'" and valeur[-1]=="'" :
455              low=low+2
456              high=high+2
457           if len(valeur) < low :return 0
458           if len(valeur) > high:return 0
459           return 1
460
461 class OrdList(ListVal):
462       """
463           Verification qu'une liste est croissante ou decroissante
464       """
465       def __init__(self,ord):
466           self.ord=ord
467           self.cata_info=""
468
469       def info(self):
470           return "liste %s" % self.ord
471
472       def info_erreur_liste(self) :
473           return "La liste doit etre en ordre "+self.ord
474
475       def verif(self,valeur):
476           if type(valeur) in (types.ListType,types.TupleType):
477              if self.ord=='croissant':
478                 var=valeur[0]
479                 for val in valeur[1:]:
480                    if val<var:return 0
481                    var=val
482                 return 1
483              elif self.ord=='decroissant':
484                 var=valeur[0]
485                 for val in valeur[1:]:
486                    if val>var:return 0
487                    var=val
488                 return 1
489           else:
490              return 1
491
492       def verif_item(self,valeur):
493           return 1
494
495       def get_into(self,liste_courante=None,into_courant=None):
496           """
497           Methode get_into spécifique pour validateur OrdList, on retourne
498           une liste de choix qui ne contient aucune valeur de into_courant
499           dont la valeur est inférieure à la dernière valeur de
500           liste_courante, si elle est différente de None.
501           """
502           if into_courant is None:
503              return None
504           elif not liste_courante :
505              return into_courant
506           else:
507              liste_choix=[]
508              last_val=liste_choix[-1]
509              for e in into_courant:
510                  if self.ord=='croissant' and e <= last_val:continue
511                  if self.ord=='decroissant' and e >= last_val:continue
512                  liste_choix.append(e)
513              return liste_choix
514
515 CoercableFuncs = { types.IntType:     int,
516                    types.LongType:    long,
517                    types.FloatType:   float,
518                    types.ComplexType: complex,
519                    types.UnicodeType: unicode }
520
521 class TypeVal(ListVal):
522       """
523           Cette classe est un validateur qui controle qu'une valeur
524           est bien du type Python attendu.
525           Pour une liste on verifie que tous les elements sont du bon type.
526       """
527       def __init__(self, aType):
528           if type(aType) != types.TypeType:
529              aType=type(aType)
530           self.aType=aType
531           try:
532              self.coerce=CoercableFuncs[ aType ]
533           except:
534              self.coerce = self.identity
535
536       def info(self):
537           return "valeur de %s" % self.aType
538
539       def identity ( self, value ):
540           if type( value ) == self.aType:
541              return value
542           raise ValError
543
544       def verif_item(self,valeur):
545           try:
546              self.coerce(valeur)
547           except:
548              return 0
549           return 1
550
551 class InstanceVal(ListVal):
552       """
553           Cette classe est un validateur qui controle qu'une valeur est
554           bien une instance (au sens Python) d'une classe
555           Pour une liste on verifie chaque element de la liste
556       """
557       def __init__(self,aClass):
558           if type(aClass) == types.InstanceType:
559              aClass=aClass.__class__
560           self.aClass=aClass
561
562       def info(self):
563           return "valeur d'instance de %s" % self.aClass.__name__
564
565       def verif_item(self,valeur):
566           if not isinstance(valeur,self.aClass): return 0
567           return 1
568
569 def ImpairVal(valeur):
570     """
571         Cette fonction est un validateur. Elle verifie que la valeur passee
572         est bien un nombre impair.
573     """
574     if type(valeur) in (types.ListType,types.TupleType):
575        for val in valeur:
576            if val % 2 != 1:return 0
577        return 1
578     else:
579        if valeur % 2 != 1:return 0
580        return 1
581
582 ImpairVal.info="valeur impaire"
583     
584 class F1Val(Valid):
585       """
586           Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
587           que la somme des cles A et B vaut une valeur donnee
588           en parametre du validateur
589       """
590       def __init__(self,somme=10):
591           self.somme=somme
592           self.cata_info=""
593
594       def info(self):
595           return "valeur %s pour la somme des cles A et B " % self.somme
596
597       def verif(self,valeur):
598           if type(valeur) in (types.ListType,types.TupleType):
599              for val in valeur:
600                 if not val.has_key("A"):return 0
601                 if not val.has_key("B"):return 0
602                 if val["A"]+val["B"]  != self.somme:return 0
603              return 1
604           else:
605              if not valeur.has_key("A"):return 0
606              if not valeur.has_key("B"):return 0
607              if valeur["A"]+valeur["B"]  != self.somme:return 0
608              return 1
609
610 class FunctionVal(Valid):
611       """
612           Cette classe est un validateur qui est initialise avec une fonction
613       """
614       def __init__(self,function):
615           self.function=function
616
617       def info(self):
618           return self.function.info
619
620       def verif(self,valeur):
621           return self.function(valeur)
622
623 class OrVal(Valid):
624       """
625           Cette classe est un validateur qui controle une liste de validateurs
626           Elle verifie qu'au moins un des validateurs de la liste valide la valeur
627       """
628       def __init__(self,validators=()):
629           if type(validators) not in (types.ListType,types.TupleType): 
630              validators=(validators,)
631           self.validators=[]
632           for validator in validators:
633               if type(validator) == types.FunctionType:
634                  self.validators.append(FunctionVal(validator))
635               else:
636                  self.validators.append(validator)
637           self.cata_info=""
638
639       def info(self):
640           return "\n ou ".join([v.info() for v in self.validators])
641
642       def info_erreur_item(self):
643           l=[]
644           for v in self.validators:
645               err=v.info_erreur_item()
646               if err != " " : l.append(err)
647           chaine=" \n ou ".join(l)
648           return chaine
649
650       def info_erreur_liste(self):
651           l=[]
652           for v in self.validators:
653               err=v.info_erreur_liste()
654               if err != " " : l.append(err)
655           chaine=" \n ou ".join(l)
656           return chaine
657
658       def is_list(self):
659           """
660              Si plusieurs validateurs sont reliés par un OU
661              il suffit qu'un seul des validateurs attende une liste
662              pour qu'on considère que leur union attend une liste.
663           """
664           for validator in self.validators:
665               v=validator.is_list()
666               if v :
667                  return 1
668           return 0
669
670       def verif(self,valeur):
671           for validator in self.validators:
672               v=validator.verif(valeur)
673               if v :
674                  return 1
675           return 0
676
677       def verif_item(self,valeur):
678           for validator in self.validators:
679               v=validator.verif_item(valeur)
680               if v :
681                  return 1
682           return 0
683
684       def verif_cata(self):
685           infos=[]
686           for validator in self.validators:
687               v=validator.verif_cata()
688               if not v :infos.append(validator.cata_info)
689           if infos:
690              self.cata_info="\n".join(infos)
691              return 0
692           self.cata_info=""
693           return 1
694
695       def has_into(self):
696           """
697           Dans le cas ou plusieurs validateurs sont reliés par un OU
698           il faut que tous les validateurs proposent un choix pour
699           qu'on considère que leur union propose un choix.
700           Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
701           En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
702           """
703           for validator in self.validators:
704               v=validator.has_into()
705               if not v :
706                  return 0
707           return 1
708
709       def get_into(self,liste_courante=None,into_courant=None):
710           """
711           Dans le cas ou plusieurs validateurs sont reliés par un OU
712           tous les validateurs doivent proposer un choix pour
713           qu'on considère que leur union propose un choix. Tous les choix
714           proposés par les validateurs sont réunis (opérateur d'union).
715           Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
716           En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un 
717           choix (1,2,3,4,5,6)       
718           """
719           validator_into=[]
720           for validator in self.validators:
721               v_into=validator.get_into(liste_courante,into_courant)
722               if v_into is None:
723                  return v_into
724               validator_into.extend(v_into)
725           return validator_into
726
727       def valide_liste_partielle(self,liste_courante=None):
728           """
729            Méthode de validation de liste partielle pour le validateur Or.
730            Si un des validateurs gérés par le validateur Or considère la
731            liste comme valide, le validateur Or la considère comme valide.
732           """
733           for validator in self.validators:
734               v=validator.valide_liste_partielle(liste_courante)
735               if v :
736                  return 1
737           return 0
738
739 class AndVal(Valid):
740       """
741           Cette classe est un validateur qui controle une liste de validateurs
742           Elle verifie que tous les validateurs de la liste valident la valeur
743       """
744       def __init__(self,validators=()):
745           if type(validators) not in (types.ListType,types.TupleType): 
746              validators=(validators,)
747           self.validators=[]
748           for validator in validators:
749               if type(validator) == types.FunctionType:
750                  self.validators.append(FunctionVal(validator))
751               else:
752                  self.validators.append(validator)
753           self.cata_info=""
754
755       def info(self):
756           return "\n et ".join([v.info() for v in self.validators])
757
758       def info_erreur_item(self):
759           chaine=""
760           a=1
761           for v in self.validators:
762               if v.info_erreur_item() != " " :
763                  if a==1:
764                     chaine=v.info_erreur_item()
765                     a=0
766                  else:
767                     chaine=chaine+" \n et "+v.info_erreur_item()
768           return chaine
769
770       def info_erreur_liste(self):
771           a=1
772           for v in self.validators:
773               if v.info_erreur_liste() != " " :
774                  if a==1:
775                     chaine=v.info_erreur_liste()
776                     a=0
777                  else:
778                     chaine=chaine+" \n et "+v.info_erreur_liste()
779           return chaine
780
781       def verif(self,valeur):
782           for validator in self.validators:
783               v=validator.verif(valeur)
784               if not v :
785                  self.local_info=validator.info()
786                  return 0
787           return 1
788
789       def verif_item(self,valeur):
790           for validator in self.validators:
791               v=validator.verif_item(valeur)
792               if not v :
793                  # L'info n'est probablement pas la meme que pour verif ???
794                  self.local_info=validator.info()
795                  return 0
796           return 1
797
798       def verif_cata(self):
799           infos=[]
800           for validator in self.validators:
801               v=validator.verif_cata()
802               if not v :infos.append(validator.cata_info)
803           if infos:
804              self.cata_info="\n".join(infos)
805              return 0
806           self.cata_info=""
807           return 1
808
809       def valide_liste_partielle(self,liste_courante=None):
810           """
811            Méthode de validation de liste partielle pour le validateur And.
812            Tous les validateurs gérés par le validateur And doivent considérer
813            la liste comme valide, pour que le validateur And la considère
814            comme valide.
815           """
816           for validator in self.validators:
817               v=validator.valide_liste_partielle(liste_courante)
818               if not v :
819                  return 0
820           return 1
821
822       def is_list(self):
823           """
824           Si plusieurs validateurs sont reliés par un ET
825           il faut que tous les validateurs attendent une liste
826           pour qu'on considère que leur intersection attende une liste.
827           Exemple Range(2,5) ET Card(1) n'attend pas une liste
828           Range(2,5) ET Pair attend une liste
829           """
830           for validator in self.validators:
831               v=validator.is_list()
832               if v == 0 :
833                  return 0
834           return 1
835
836       def has_into(self):
837           """
838           Dans le cas ou plusieurs validateurs sont reliés par un ET
839           il suffit qu'un seul validateur propose un choix pour
840           qu'on considère que leur intersection propose un choix.
841           Exemple : Enum(1,2,3) ET entier pair, propose un choix
842           En revanche, entier pair ET superieur à 10 ne propose pas de choix
843           """
844           for validator in self.validators:
845               v=validator.has_into()
846               if v :
847                  return 1
848           return 0
849
850       def get_into(self,liste_courante=None,into_courant=None):
851           """
852           Dans le cas ou plusieurs validateurs sont reliés par un ET
853           il suffit qu'un seul validateur propose un choix pour
854           qu'on considère que leur intersection propose un choix. Tous les
855           choix proposés par les validateurs sont croisés (opérateur
856           d'intersection)
857           Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
858           En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
859           """
860           for validator in self.validators:
861               into_courant=validator.get_into(liste_courante,into_courant)
862               if into_courant in ([],None):break
863           return into_courant
864
865 def do_liste(validators):
866     """ 
867        Convertit une arborescence de validateurs en OrVal ou AndVal
868        validators est une liste de validateurs ou de listes ou de tuples
869     """
870     valids=[]
871     for validator in validators:
872         if type(validator) == types.FunctionType:
873            valids.append(FunctionVal(validator))
874         elif type(validator) == types.TupleType:
875            valids.append(OrVal(do_liste(validator)))
876         elif type(validator) == types.ListType:
877            valids.append(AndVal(do_liste(validator)))
878         else:
879            valids.append(validator)
880     return valids
881
882 def validatorFactory(validator):
883     if type(validator) == types.FunctionType:
884        return FunctionVal(validator)
885     elif type(validator) == types.TupleType:
886        return OrVal(do_liste(validator))
887     elif type(validator) == types.ListType:
888        return AndVal(do_liste(validator))
889     else:
890        return validator