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