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