]> SALOME platform Git repositories - tools/eficas.git/commitdiff
Salome HOME
CCAR: Mise a niveau Noyau avec Aster 7.2.11 + correction bug sur les blocs
authoreficas <>
Thu, 29 Jan 2004 18:21:17 +0000 (18:21 +0000)
committereficas <>
Thu, 29 Jan 2004 18:21:17 +0000 (18:21 +0000)
+ reintegration méthodes surchargées dans Ihm

Noyau/N_ETAPE.py
Noyau/N_JDC.py
Noyau/N_MACRO_ETAPE.py
Noyau/N_MCBLOC.py
Noyau/N_MCCOMPO.py
Noyau/N_MCLIST.py
Noyau/N_MCSIMP.py
Noyau/N_OBJECT.py
Noyau/N_VALIDATOR.py

index cb968d3ad2b54b7ac4806f8d6e4e0ca57359a991..1e703ba0c5586f1ac65f06a2b287758f1e961413 100644 (file)
@@ -361,3 +361,12 @@ class ETAPE(N_MCCOMPO.MCCOMPO):
      self.etape=self
      for mocle in self.mc_liste:
         mocle.reparent(self)
+
+   def get_cmd(self,nomcmd):
+      """
+          Méthode pour recuperer la definition d'une commande
+          donnee par son nom dans les catalogues declares
+          au niveau du jdc
+          Appele par un ops d'une macro en Python
+      """
+      return self.jdc.get_cmd(nomcmd)
index d538ca71ab90dd91437dfc54e42f2d66bf3c761b..ee40f7ced01b66bbbd435647e22ccc66acc1bc73 100644 (file)
@@ -1,4 +1,4 @@
-#@ MODIF N_JDC Noyau  DATE 26/09/2003   AUTEUR DURAND C.DURAND 
+#@ MODIF N_JDC Noyau  DATE 05/11/2003   AUTEUR CAMBIER S.CAMBIER 
 #            CONFIGURATION MANAGEMENT OF EDF VERSION
 # ======================================================================
 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
@@ -100,6 +100,7 @@ NONE = None
       self.condition_context={}
       self.index_etape_courante=0
       self.UserError="UserError"
+      self.alea = None
 
    def compile(self):
       """
@@ -323,9 +324,11 @@ NONE = None
                                " a l unite %s" % unite)
          if not os.path.exists(file):
             raise AsException("%s n'est pas un fichier existant" % unite)
-      fproc=open(file,'r')
-      text=string.replace(fproc.read(),'\r\n','\n')
-      fproc.close()
+         fproc=open(file,'r')
+         text=fproc.read()
+         fproc.close()
+      if file == None : return None,None
+      text=string.replace(text,'\r\n','\n')
       linecache.cache[file]=0,0,string.split(text,'\n'),file
       return file,text
 
@@ -394,9 +397,12 @@ NONE = None
       if index_etape >= self.index_etape_courante:
          # On calcule le contexte en partant du contexte existant
          d=self.current_context
+         if self.index_etape_courante==0 and self.context_ini:
+            d.update(self.context_ini)
          liste_etapes=self.etapes[self.index_etape_courante:index_etape]
       else:
          d=self.current_context={}
+         if self.context_ini:d.update(self.context_ini)
          liste_etapes=self.etapes
 
       for e in liste_etapes:
@@ -409,3 +415,14 @@ NONE = None
 
    def get_global_contexte(self):
       return self.g_context.copy()
+
+   def get_cmd(self,nomcmd):
+      """
+          Méthode pour recuperer la definition d'une commande
+          donnee par son nom dans les catalogues declares
+          au niveau du jdc
+      """
+      for cata in self.cata:
+          if hasattr(cata,nomcmd):
+             return getattr(cata,nomcmd)
+
index 953b0d94b2ca9eb05b2284b6bc8ecac0fdf03fb3..d663047e74c5e67e5be9cbc7d28ceebe4c946857 100644 (file)
@@ -529,6 +529,17 @@ class MACRO_ETAPE(N_ETAPE.ETAPE):
       d.update(self.g_context)
       return d
 
+   def copy(self):
+      """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
+          et sans sd
+          On surcharge la methode de ETAPE pour exprimer que les concepts crees
+          par la MACRO d'origine ne sont pas crees par la copie mais eventuellement
+          seulement utilises
+      """
+      etape=N_ETAPE.ETAPE.copy(self)
+      etape.sdprods=[]
+      return etape
+
 
 
 
index 60f3c80df5077e85dcd74b02d05d8fbb06223293..34fdb45ec70eb15717df7c3b8ff7a8e4ad569360 100644 (file)
@@ -81,15 +81,38 @@ class MCBLOC(N_MCCOMPO.MCCOMPO):
           
       """
       dico={}
-      for v in self.mc_liste:
-        val = v.get_valeur()
-        if type(val)==types.DictionaryType:
-          for i,w in val.items():
-            dico[i]=w
-        else :
-          dico[v.nom]=val
+      for mocle in self.mc_liste:
+        if mocle.isBLOC():
+           # Si mocle est un BLOC, on inclut ses items dans le dictionnaire
+           # représentatif de la valeur de self. Les mots-clés fils de blocs sont
+           # donc remontés au niveau supérieur.
+           dico.update(mocle.get_valeur())
+        else:
+           dico[mocle.nom]=mocle.get_valeur()
+
+      # On rajoute tous les autres mots-clés locaux possibles avec la valeur
+      # par défaut ou None
+      # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d')
+      # et caché ('c')
+      # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement
+      # une condition.
+      for k,v in self.definition.entites.items():
+        if not dico.has_key(k):
+           if v.label == 'SIMP':
+              # Mot clé simple
+              dico[k]=v.defaut
+           elif v.label == 'FACT':
+                if v.statut in ('c','d') :
+                   # Mot clé facteur avec défaut ou caché provisoire
+                   dico[k]=v(val=None,nom=k,parent=self)
+                   # On demande la suppression des pointeurs arrieres
+                   # pour briser les eventuels cycles
+                   dico[k].supprime()
+                else:
+                   dico[k]=None
+
       return dico
-  
+
    def isBLOC(self):
       """
           Indique si l'objet est un BLOC
index 56fa972dea554d74a38de4774ab819dad128d364..bb77a945d3be8fd6bebcb94fe5327d1ed3b75400 100644 (file)
@@ -1,4 +1,4 @@
-#@ MODIF N_MCCOMPO Noyau  DATE 03/09/2002   AUTEUR GNICOLAS G.NICOLAS 
+#@ MODIF N_MCCOMPO Noyau  DATE 28/10/2003   AUTEUR DURAND C.DURAND 
 #            CONFIGURATION MANAGEMENT OF EDF VERSION
 # ======================================================================
 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
@@ -77,7 +77,7 @@ class MCCOMPO(N_OBJECT.OBJECT):
       # A ce stade, mc_liste ne contient que les fils de l'objet courant
       # args ne contient plus que des mots-clés qui n'ont pas été attribués car ils sont
       #      à attribuer à des blocs du niveau inférieur ou bien sont des mots-clés erronés
-      dico_valeurs = self.cree_dict_valeurs(mc_liste)
+      dico_valeurs = self.cree_dict_condition(mc_liste,condition=1)
       for k,v in self.definition.entites.items():
          if v.label != 'BLOC':continue
          # condition and a or b  : Equivalent de l'expression :  condition ? a : b du langage C
@@ -91,7 +91,9 @@ class MCCOMPO(N_OBJECT.OBJECT):
             bloc = v(nom=k,val=args,parent=self)
             mc_liste.append(bloc)
             args=bloc.reste_val
-            dico_valeurs = self.cree_dict_valeurs(mc_liste)
+            # On ne recalcule pas le contexte car on ne tient pas compte des blocs
+            # pour évaluer les conditions de présence des blocs
+            #dico_valeurs = self.cree_dict_valeurs(mc_liste)
 
       # On conserve les arguments superflus dans l'attribut reste_val
       self.reste_val=args
@@ -113,27 +115,27 @@ class MCCOMPO(N_OBJECT.OBJECT):
       else:
          return mc_liste
 
-   def cree_dict_valeurs(self,liste=[]):
+   def cree_dict_valeurs(self,liste=[],condition=0):
       """ 
-        Cette méthode crée le contexte de l'objet courant sous la forme 
-        d'un dictionnaire.
-        L'opération consiste à transformer une liste d'OBJECT en un 
-        dictionnaire.
-        Ce dictionnaire servira de contexte pour évaluer les conditions des 
-        blocs fils.
+        Cette méthode crée un contexte (sous la forme d'un dictionnaire)
+        à partir des valeurs des mots clés contenus dans l'argument liste.
+        L'opération consiste à parcourir la liste (d'OBJECT) et à la 
+        transformer en un dictionnaire dont les clés sont les noms des
+        mots clés et les valeurs dépendent du type d'OBJECT.
+        Ce dictionnaire servira de liste d'arguments d'appel pour les
+        fonctions sd_prod de commandes et ops de macros ou de contexte
+        d'évaluation des conditions de présence de BLOC.
+
+        Si l'argument condition de la méthode vaut 1, on ne 
+        remonte pas les valeurs des mots clés contenus dans des blocs
+        pour eviter les bouclages.
 
         Cette méthode réalise les opérations suivantes en plus de transformer 
         la liste en dictionnaire :
 
-        - ajouter tous les mots-clés non présents avec la valeur None
-
-        - ajouter tous les mots-clés globaux (attribut position = 'global' 
-          et 'global_jdc')
-
-        ATTENTION : -- on ne remonte pas (semble en contradiction avec la 
-                      programmation de la méthode get_valeur du bloc) les 
-                      mots-clé fils d'un bloc au niveau du
-                      contexte car celà peut générer des erreurs.
+           - ajouter tous les mots-clés non présents avec la valeur None
+           - ajouter tous les mots-clés globaux (attribut position = 'global' 
+             et 'global_jdc')
 
         L'argument liste est, en général, une mc_liste en cours de 
         construction, contenant les mots-clés locaux et les blocs déjà créés.
@@ -141,57 +143,56 @@ class MCCOMPO(N_OBJECT.OBJECT):
       """
       dico={}
       for v in liste:
-        k=v.nom
-        val = v.get_valeur()
-        # Si val est un dictionnaire, on inclut ses items dans le dictionnaire
-        # représentatif du contexte. Les blocs sont retournés par get_valeur
-        # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont
-        # donc remontés au niveau du contexte.
-        if type(val)==types.DictionaryType:
-          for i,w in val.items():
-            dico[i]=w
+        if v.isBLOC():
+           # Si v est un BLOC, on inclut ses items dans le dictionnaire
+           # représentatif du contexte. Les blocs sont retournés par get_valeur
+           # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont
+           # donc remontés au niveau du contexte.
+           if not condition:dico.update(v.get_valeur())
         else:
-          dico[k]=val
-      # on rajoute tous les autres mots-clés locaux possibles avec la valeur 
+           dico[v.nom]=v.get_valeur()
+
+      # On rajoute tous les autres mots-clés locaux possibles avec la valeur 
       # par défaut ou None
-      # Pour les mots-clés facteurs, on ne tient pas compte du défaut 
-      # (toujours None)
+      # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d')
+      # et caché ('c')
+      # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement
+      # une condition.
       for k,v in self.definition.entites.items():
         if not dico.has_key(k):
            if v.label == 'SIMP':
+              # Mot clé simple
               dico[k]=v.defaut
-              # S il est declare global il n est pas necessaire de l ajouter
-              # aux mots cles globaux de l'etape
-              # car la methode recherche_mc_globaux les rajoutera
-           elif v.label == 'FACT' and v.statut in ('c','d') :
-              dico[k]=v(val=None,nom=k,parent=self)
-              # On demande la suppression des pointeurs arrieres
-              # pour briser les eventuels cycles
-              dico[k].supprime()
-           elif v.label != 'BLOC':
-              dico[k]=None
+           elif v.label == 'FACT' :
+              if v.statut in ('c','d') :
+                 # Mot clé facteur avec défaut ou caché provisoire
+                 dico[k]=v(val=None,nom=k,parent=self)
+                 # On demande la suppression des pointeurs arrieres
+                 # pour briser les eventuels cycles
+                 dico[k].supprime()
+              else:
+                 dico[k]=None
       # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur
       # valeur par défaut ou la valeur None
-      # on rajoute les mots-clés globaux ...
+
+      # On rajoute les mots-clés globaux sans écraser les clés existantes
       dico_mc = self.recherche_mc_globaux()
-      for nom,mc in dico_mc.items() :
-        if not dico.has_key(nom) : dico[nom]=mc.valeur
-      # Il nous reste à évaluer la présence des blocs en fonction du contexte qui a changé
-      for k,v in self.definition.entites.items():
-        if v.label != 'BLOC' : continue
-        # condition and a or b  : Equivalent de l'expression :  condition ? a : b du langage C
-        globs= self.jdc and self.jdc.condition_context or {}
-        if v.verif_presence(dico,globs):
-          # le bloc k doit etre présent : on crée temporairement l'objet MCBLOC correspondant
-          # on lui passe un parent égal à None pour qu'il ne soit pas enregistré
-          bloc = v(nom=k,val=None,parent=None)
-          dico_bloc = bloc.cree_dict_valeurs()
-          bloc.supprime()
-          # on va updater dico avec dico_bloc en veillant à ne pas écraser
-          # des valeurs déjà présentes
-          for cle in dico_bloc.keys():
-            if not dico.has_key(cle):
-              dico[cle]=dico_bloc[cle]
+      dico_mc.update(dico)
+      dico=dico_mc
+
+      return dico
+
+   def cree_dict_condition(self,liste=[],condition=0):
+      """
+          Methode pour construire un contexte qui servira dans l'évaluation
+          des conditions de présence de blocs. Si une commande a un concept
+          produit réutilisé, on ajoute la clé 'reuse'
+      """
+      dico=self.cree_dict_valeurs(liste,condition=1)
+      # On ajoute la cle "reuse" pour les MCCOMPO qui ont un attribut reuse. A destination
+      # uniquement des commandes. Ne devrait pas etre dans cette classe mais dans une classe dérivée
+      if not dico.has_key('reuse') and hasattr(self,'reuse'):
+         dico['reuse']=self.reuse
       return dico
 
    def recherche_mc_globaux(self):
@@ -292,9 +293,13 @@ class MCCOMPO(N_OBJECT.OBJECT):
       for v in self.mc_liste:
         if v.nom == name : return v
       if restreint == 'non' :
-        for k,v in self.definition.entites.items():
-          if k == name:
-            if v.valeur != None : return v(None,k,None)
+        try:
+           entite=self.definition.entites[name]
+           if entite.label == 'SIMP' or (entite.label == 'FACT' and entite.statut in ( 'c', 'd')):
+              return entite(None,name,None)
+        except:
+           pass
+
       return None
 
    def append_mc_global(self,mc):
index 9b21cdf941b8e11b5de0c7a8c7aaefa1bab31a69..49736eb1586449587333b421f1cc4f91f1a66b58 100644 (file)
@@ -144,3 +144,14 @@ class MCList(UserList.UserList):
       self.etape=parent.etape
       for mcfact in self.data:
         mcfact.reparent(parent)
+
+   def get_etape(self):
+      """
+         Retourne l'étape à laquelle appartient self
+         Un objet de la catégorie etape doit retourner self pour indiquer que
+         l'étape a été trouvée
+         XXX double emploi avec self.etape ???
+      """
+      if self.parent == None: return None
+      return self.parent.get_etape()
+
index 7df9f9fd5f001475ea6c89bb0a72eb417a50a2c7..5e123bd147d93a0a6eeb00930a708a7d329841b4 100644 (file)
@@ -99,39 +99,39 @@ class MCSIMP(N_OBJECT.OBJECT):
       visitor.visitMCSIMP(self)
 
    def copy(self):
-    """ Retourne une copie de self """
-    objet = self.makeobjet()
-    # il faut copier les listes et les tuples mais pas les autres valeurs
-    # possibles (réel,SD,...)
-    if type(self.valeur) in (types.ListType,types.TupleType):
-       objet.valeur = copy(self.valeur)
-    else:
-       objet.valeur = self.valeur
-    objet.val = objet.valeur
-    return objet
+      """ Retourne une copie de self """
+      objet = self.makeobjet()
+      # il faut copier les listes et les tuples mais pas les autres valeurs
+      # possibles (réel,SD,...)
+      if type(self.valeur) in (types.ListType,types.TupleType):
+         objet.valeur = copy(self.valeur)
+      else:
+         objet.valeur = self.valeur
+      objet.val = objet.valeur
+      return objet
 
    def makeobjet(self):
-    return self.definition(val = None, nom = self.nom,parent = self.parent)
+      return self.definition(val = None, nom = self.nom,parent = self.parent)
 
    def reparent(self,parent):
-     """
+      """
          Cette methode sert a reinitialiser la parente de l'objet
-     """
-     self.parent=parent
-     self.jdc=parent.jdc
-     self.etape=parent.etape
+      """
+      self.parent=parent
+      self.jdc=parent.jdc
+      self.etape=parent.etape
 
    def get_sd_utilisees(self):
-    """ 
-        Retourne une liste qui contient la SD utilisée par self si c'est le cas
-        ou alors une liste vide
-    """
-    l=[]
-    if type(self.valeur) == types.InstanceType:
-      #XXX Est ce différent de isinstance(self.valeur,ASSD) ??
-      if issubclass(self.valeur.__class__,ASSD) : l.append(self.valeur)
-    elif type(self.valeur) in (types.TupleType,types.ListType):
-      for val in self.valeur :
-         if type(val) == types.InstanceType:
-            if issubclass(val.__class__,ASSD) : l.append(val)
-    return l
+      """ 
+          Retourne une liste qui contient la SD utilisée par self si c'est le cas
+          ou alors une liste vide
+      """
+      l=[]
+      if type(self.valeur) == types.InstanceType:
+        #XXX Est ce différent de isinstance(self.valeur,ASSD) ??
+        if issubclass(self.valeur.__class__,ASSD) : l.append(self.valeur)
+      elif type(self.valeur) in (types.TupleType,types.ListType):
+        for val in self.valeur :
+           if type(val) == types.InstanceType:
+              if issubclass(val.__class__,ASSD) : l.append(val)
+      return l
index 487127900413171f3b81c1823b6271fdcd1684d8..52abd6cdcd76ea2746b843e858c98fbb771a628d 100644 (file)
@@ -89,3 +89,10 @@ class OBJECT:
       else:
         return val
 
+   def reparent(self,parent):
+      """
+         Cette methode sert a reinitialiser la parente de l'objet
+      """
+      self.parent=parent
+      self.jdc=parent.jdc
+
index 1fcbe331df9fefc0e41c7891f83be1f191b997ca..6db3a475cb2986d4e5397756a53653138829ad6e 100644 (file)
@@ -29,8 +29,8 @@ class Valid:
    """
         Cette classe est la classe mere des validateurs Accas
         Elle doit etre derivee 
-        Elle ne presente que la signature des methodes
-        indispensables pour son bon fonctionnement
+        Elle presente la signature des methodes indispensables pour son bon 
+        fonctionnement et dans certains cas leur comportement par défaut.
 
         @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
         @type cata_info: C{string}
@@ -43,8 +43,42 @@ class Valid:
        raise "Must be implemented"
 
    def info(self):
+       """
+          Cette methode retourne une chaine de caractères informative sur
+          la validation demandée par le validateur. Elle est utilisée
+          pour produire le compte-rendu de validité du mot clé associé.
+       """
        return "valeur valide" 
 
+   def aide(self):
+       """
+          Cette methode retourne une chaine de caractère qui permet 
+          de construire un message d'aide en ligne.
+          En général, le message retourné est le meme que celui retourné par la
+          méthode info.
+       """
+       return self.info()
+
+   def info_erreur_item(self):
+       """
+          Cette méthode permet d'avoir un message d'erreur pour un item
+          dans une liste dans le cas ou le validateur fait des vérifications
+          sur les items d'une liste. Si le validateur fait seulement des
+          vérifications sur la liste elle meme et non sur ses items, la méthode
+          doit retourner une chaine vide.
+       """
+       return " "
+
+   def info_erreur_liste(self):
+       """
+          Cette méthode a un comportement complémentaire de celui de
+          info_erreur_item. Elle retourne un message d'erreur lié uniquement
+          aux vérifications sur la liste elle meme et pas sur ses items.
+          Dans le cas où le validateur ne fait pas de vérification sur des
+          listes, elle retourne une chaine vide
+       """
+       return " "
+
    def verif(self,valeur):
        """
            Cette methode sert a verifier si la valeur passee en argument est consideree
@@ -58,9 +92,29 @@ class Valid:
        """
        raise "Must be implemented"
    
-   def error(self,valeur):
+   def verif_item(self,valeur):
+       """
+          La methode verif du validateur effectue une validation complete de
+          la valeur. valeur peut etre un scalaire ou une liste. Le validateur
+          doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
+          methode is_list doit retourner 1).
+          La methode valid_item sert pour effectuer des validations partielles
+          de liste. Elle doit uniquement verifier la validite d'un item de
+          liste mais pas les caracteristiques de la liste.
+       """
        return 0
 
+   def valide_liste_partielle(self,liste_courante):
+       """
+          Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
+          ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
+          veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
+          comme invalide.
+          En général un validateur effectue la meme validation pour les listes partielles et les
+          listes complètes.
+       """
+       return self.verif(liste_courante)
+
    def verif_cata(self):
        """
            Cette methode sert a realiser des verifications du validateur lui meme.
@@ -74,7 +128,115 @@ class Valid:
        """
        return 1
 
-class RangeVal(Valid):
+   def is_list(self):
+       """
+          Cette méthode retourne un entier qui indique si le validateur
+          permet les listes (valeur 1) ou ne les permet pas (valeur 0).
+          Par défaut, un validateur n'autorise que des scalaires.
+       """
+       return 0
+
+   def has_into(self):
+       """
+          Cette méthode retourne un entier qui indique si le validateur
+          propose une liste de choix (valeur 1) ou n'en propose pas.
+          Par défaut, un validateur n'en propose pas.
+       """
+       return 0
+
+   def get_into(self,liste_courante=None,into_courant=None):
+       """
+          Cette méthode retourne la liste de choix proposée par le validateur.
+          Si le validateur ne propose pas de liste de choix, la méthode
+          retourne None.
+          L'argument d'entrée liste_courante, s'il est différent de None, donne
+          la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
+          méthode get_into doit calculer la liste des choix en en tenant
+          compte. Par exemple, si le validateur n'autorise pas les répétitions,
+          la liste des choix retournée ne doit pas contenir les choix déjà
+          contenus dans liste_courante.
+          L'argument d'entrée into_courant, s'il est différent de None, donne
+          la liste des choix proposés par d'autres validateurs. Dans ce cas,
+          la méthode get_into doit calculer la liste des choix à retourner
+          en se limitant à cette liste initiale. Par exemple, si into_courant
+          vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
+          la méthode ne doit retourner que (3,).
+
+          La méthode get_into peut retourner une liste vide [], ce qui veut
+          dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
+          peut etre normale : l''utilisateur a utilisé tous les choix, ou
+          résulter d'une incohérence des validateurs :
+          choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
+          faire la différence entre ces deux situations.
+       """
+       return into_courant
+
+   def is_eval(self,valeur):
+       """
+           Cette méthode indique si valeur est un objet de type EVAL ou autre
+           que l'on ne cherchera pas à evaluer et qui doit etre considere
+           comme toujours valide. Si c'est un objet de ce type elle retourne
+           la valeur 1 sinon la valeur 0
+       """
+       return type(valeur) == types.InstanceType and valeur.__class__.__name__ in ('EVAL',
+                    'entier','reel','chaine', 'complexe','liste','PARAMETRE_EVAL')
+
+   def is_param(self,valeur):
+       """
+           Cette méthode indique si valeur est un objet de type PARAMETRE
+           dont on cherchera à evaluer la valeur (valeur.valeur)
+       """
+       return type(valeur) == types.InstanceType and valeur.__class__.__name__ in ('PARAMETRE',)
+
+   def is_unknown(self,valeur):
+       """
+           Cette méthode indique si valeur est un objet de type inconnu
+           c'est à dire ni de type EVAL ni de type PARAMETRE
+       """
+       return type(valeur) == types.InstanceType and valeur.__class__.__name__ not in ('EVAL',
+                    'entier','reel','chaine', 'complexe','liste','PARAMETRE_EVAL','PARAMETRE')
+
+class ListVal(Valid):
+   """
+       Cette classe sert de classe mère pour tous les validateurs qui acceptent
+       des listes.
+   """
+   def is_list(self):
+       return 1
+
+   def get_into(self,liste_courante=None,into_courant=None):
+       """
+          Cette méthode get_into effectue un traitement général qui consiste
+          a filtrer la liste de choix into_courant, si elle existe, en ne
+          conservant que les valeurs valides (appel de la méthode valid).
+       """
+       if into_courant is None:
+          return None
+       else:
+          liste_choix=[]
+          for e in into_courant:
+              if self.verif(e):
+                 liste_choix.append(e)
+          return liste_choix
+
+   def verif(self,valeur):
+       """
+          Méthode verif pour les validateurs de listes. Cette méthode
+          fait appel à la méthode verif_item sur chaque élément de la 
+          liste. Si valeur est un paramètre, on utilise sa valeur effective
+          valeur.valeur.
+       """
+       if self.is_param(valeur):
+          valeur=valeur.valeur
+       if type(valeur) in (types.ListType,types.TupleType):
+          for val in valeur:
+              if not self.verif_item(val):
+                 return 0
+          return 1
+       else:
+          return self.verif_item(valeur)
+
+class RangeVal(ListVal):
       """
           Exemple de classe validateur : verification qu'une valeur
           est dans un intervalle.
@@ -91,16 +253,12 @@ class RangeVal(Valid):
       def info(self):
           return "valeur dans l'intervalle %s , %s" %(self.low,self.high)
 
-      def verif(self,valeur):
-          if type(valeur) in (types.ListType,types.TupleType):
-             for val in valeur:
-                if val < self.low :return 0
-                if val > self.high:return 0
-             return 1
-          else:
-             if valeur < self.low :return 0
-             if valeur > self.high:return 0
-             return 1
+      def verif_item(self,valeur):
+          return valeur > self.low and valeur < self.high
+
+      def info_erreur_item(self) :
+          return "La valeur doit être comprise entre %s et %s" % (self.low,
+                                                                  self.high)
 
       def verif_cata(self):
           if self.low > self.high : return 0
@@ -120,7 +278,28 @@ class CardVal(Valid):
           self.cata_info="%s doit etre inferieur a %s" % (min,max)
 
       def info(self):
-          return "longueur comprise entre  %s et %s" % (self.min,self.max)
+          return "longueur de liste comprise entre  %s et %s" % (self.min,self.max)
+
+      def info_erreur_liste(self):
+          return "La cardinalité de la liste doit être comprise entre %s et %s" % (self.min,self.max)
+
+      def is_list(self):
+          return self.max == '**' or self.max > 1
+
+      def get_into(self,liste_courante=None,into_courant=None):
+          if into_courant is None:
+             return None
+          elif liste_courante is None:
+             return into_courant
+          elif self.max == '**':
+             return into_courant
+          elif len(liste_courante) < self.max:
+             return into_courant
+          else:
+             return []
+
+      def verif_item(self,valeur):
+          return 1
 
       def verif(self,valeur):
           if type(valeur) in (types.ListType,types.TupleType):
@@ -136,7 +315,14 @@ class CardVal(Valid):
           if self.min != '**' and self.max != '**' and self.min > self.max : return 0
           return 1
 
-class PairVal(Valid):
+      def valide_liste_partielle(self,liste_courante=None):
+          validite=1
+          if liste_courante != None :
+             if len(liste_courante) > self.max :
+                validite=0
+          return validite
+
+class PairVal(ListVal):
       """
           Exemple de classe validateur : verification qu'une valeur
           est paire.
@@ -149,6 +335,19 @@ class PairVal(Valid):
       def info(self):
           return "valeur paire"
 
+      def info_erreur_item(self):
+          return "La valeur saisie doit être paire"
+
+      def verif_item(self,valeur):
+          if type(valeur) == types.InstanceType:
+             if self.is_eval(valeur):
+                return 1
+             elif self.is_param(valeur):
+                valeur=valeur.valeur
+             else:
+                return 0
+          return valeur % 2 == 0
+
       def verif(self,valeur):
           if type(valeur) in (types.ListType,types.TupleType):
              for val in valeur:
@@ -158,7 +357,7 @@ class PairVal(Valid):
              if valeur % 2 != 0:return 0
              return 1
 
-class EnumVal(Valid):
+class EnumVal(ListVal):
       """
           Exemple de classe validateur : verification qu'une valeur
           est prise dans une liste de valeurs.
@@ -172,16 +371,27 @@ class EnumVal(Valid):
       def info(self):
           return "valeur dans %s" % `self.into`
 
-      def verif(self,valeur):
-          if type(valeur) in (types.ListType,types.TupleType):
-             for val in valeur:
-                if val not in self.into:return 0
-             return 1
+      def verif_item(self,valeur):
+          if valeur not in self.into:return 0
+          return 1
+
+      def has_into(self):
+          return 1
+
+      def get_into(self,liste_courante=None,into_courant=None):
+          if into_courant is None:
+             liste_choix= list(self.into)
           else:
-             if valeur not in self.into:return 0
-             return 1
+             liste_choix=[]
+             for e in into_courant:
+                 if e in self.into:
+                    liste_choix.append(e)
+          return liste_choix
+
+      def info_erreur_item(self):
+          return "La valeur n'est pas dans la liste des choix possibles"
 
-class NoRepeat(Valid):
+class NoRepeat(ListVal):
       """
           Verification d'absence de doublons dans la liste.
       """
@@ -189,7 +399,13 @@ class NoRepeat(Valid):
           self.cata_info=""
 
       def info(self):
-          return ": présence de doublon dans la liste"
+          return ": pas de présence de doublon dans la liste"
+
+      def info_erreur_liste(self):
+          return "Les doublons ne sont pas permis"
+
+      def verif_item(self,valeur):
+          return 1
 
       def verif(self,valeur):
           if type(valeur) in (types.ListType,types.TupleType):
@@ -200,7 +416,23 @@ class NoRepeat(Valid):
           else:
              return 1
 
-class LongStr(Valid):
+      def get_into(self,liste_courante=None,into_courant=None):
+          """
+          Methode get_into spécifique pour validateur NoRepeat, on retourne
+          une liste de choix qui ne contient aucune valeur de into_courant
+          déjà contenue dans liste_courante
+          """
+          if into_courant is None:
+             liste_choix=None
+          else:
+             liste_choix=[]
+             for e in into_courant:
+                 if e in liste_choix: continue
+                 if liste_courante is not None and e in liste_courante: continue
+                 liste_choix.append(e)
+          return liste_choix
+
+class LongStr(ListVal):
       """
           Verification de la longueur d une chaine
       """
@@ -212,18 +444,20 @@ class LongStr(Valid):
       def info(self):
           return "longueur de la chaine entre %s et %s" %(self.low,self.high)
 
-      def verif(self,valeur):
-          if type(valeur) in (types.ListType,types.TupleType):
-             for val in valeur:
-                if len(val) < self.low :return 0
-                if len(val) > self.high:return 0
-             return 1
-          else:
-             if len(valeur) < self.low :return 0
-             if len(valeur) > self.high:return 0
-             return 1
+      def info_erreur_item(self):
+          return "Longueur de la chaine incorrecte"
+
+      def verif_item(self,valeur):
+          low=self.low
+          high=self.high
+          if valeur[0]=="'" and valeur[-1]=="'" :
+             low=low+2
+             high=high+2
+          if len(valeur) < low :return 0
+          if len(valeur) > high:return 0
+          return 1
 
-class OrdList(Valid):
+class OrdList(ListVal):
       """
           Verification qu'une liste est croissante ou decroissante
       """
@@ -234,6 +468,9 @@ class OrdList(Valid):
       def info(self):
           return "liste %s" % self.ord
 
+      def info_erreur_liste(self) :
+          return "La liste doit être en ordre "+self.ord
+
       def verif(self,valeur):
           if type(valeur) in (types.ListType,types.TupleType):
              if self.ord=='croissant':
@@ -251,6 +488,28 @@ class OrdList(Valid):
           else:
              return 1
 
+      def verif_item(self,valeur):
+          return 1
+
+      def get_into(self,liste_courante=None,into_courant=None):
+          """
+          Methode get_into spécifique pour validateur OrdList, on retourne
+          une liste de choix qui ne contient aucune valeur de into_courant
+          dont la valeur est inférieure à la dernière valeur de
+          liste_courante, si elle est différente de None.
+          """
+          if into_courant is None:
+             return None
+          elif not liste_courante :
+             return into_courant
+          else:
+             liste_choix=[]
+             last_val=liste_choix[-1]
+             for e in into_courant:
+                 if self.ord=='croissant' and e <= last_val:continue
+                 if self.ord=='decroissant' and e >= last_val:continue
+                 liste_choix.append(e)
+             return liste_choix
 
 CoercableFuncs = { types.IntType:     int,
                    types.LongType:    long,
@@ -258,7 +517,7 @@ CoercableFuncs = { types.IntType:     int,
                    types.ComplexType: complex,
                    types.UnicodeType: unicode }
 
-class TypeVal(Valid):
+class TypeVal(ListVal):
       """
           Cette classe est un validateur qui controle qu'une valeur
           est bien du type Python attendu.
@@ -281,22 +540,14 @@ class TypeVal(Valid):
              return value
           raise ValError
 
-      def verif(self,valeur):
-          if type(valeur) in (types.ListType,types.TupleType):
-             for val in valeur:
-                 try:
-                    self.coerce(val)
-                 except:
-                    return 0
-             return 1
-          else:
-             try:
-                self.coerce(valeur)
-             except:
-                return 0
-             return 1
+      def verif_item(self,valeur):
+          try:
+             self.coerce(valeur)
+          except:
+             return 0
+          return 1
 
-class InstanceVal(Valid):
+class InstanceVal(ListVal):
       """
           Cette classe est un validateur qui controle qu'une valeur est
           bien une instance (au sens Python) d'une classe
@@ -310,11 +561,7 @@ class InstanceVal(Valid):
       def info(self):
           return "valeur d'instance de %s" % self.aClass.__name__
 
-      def verif(self,valeur):
-          if type(valeur) in (types.ListType,types.TupleType):
-             for val in valeur:
-                 if not isinstance(val,self.aClass): return 0
-             return 1
+      def verif_item(self,valeur):
           if not isinstance(valeur,self.aClass): return 0
           return 1
 
@@ -375,10 +622,11 @@ class FunctionVal(Valid):
 class OrVal(Valid):
       """
           Cette classe est un validateur qui controle une liste de validateurs
-          Elle verifie qu'au moins un des validateurs de la liste valide la valeur
+          Elle verifie qu'au moins un des validateurs de la liste valide la valeur
       """
       def __init__(self,validators=()):
-          if type(validators) not in (types.ListType,types.TupleType): validators=(validators,)
+          if type(validators) not in (types.ListType,types.TupleType): 
+             validators=(validators,)
           self.validators=[]
           for validator in validators:
               if type(validator) == types.FunctionType:
@@ -390,6 +638,34 @@ class OrVal(Valid):
       def info(self):
           return "\n ou ".join([v.info() for v in self.validators])
 
+      def info_erreur_item(self):
+          l=[]
+          for v in self.validators:
+              err=v.info_erreur_item()
+              if err != " " : l.append(err)
+          chaine=" \n ou ".join(l)
+          return chaine
+
+      def info_erreur_liste(self):
+          l=[]
+          for v in self.validators:
+              err=v.info_erreur_liste()
+              if err != " " : l.append(err)
+          chaine=" \n ou ".join(l)
+          return chaine
+
+      def is_list(self):
+          """
+             Si plusieurs validateurs sont reliés par un OU
+             il suffit qu'un seul des validateurs attende une liste
+             pour qu'on considère que leur union attend une liste.
+          """
+          for validator in self.validators:
+              v=validator.is_list()
+              if v :
+                 return 1
+          return 0
+
       def verif(self,valeur):
           for validator in self.validators:
               v=validator.verif(valeur)
@@ -397,6 +673,13 @@ class OrVal(Valid):
                  return 1
           return 0
 
+      def verif_item(self,valeur):
+          for validator in self.validators:
+              v=validator.verif_item(valeur)
+              if v :
+                 return 1
+          return 0
+
       def verif_cata(self):
           infos=[]
           for validator in self.validators:
@@ -408,13 +691,58 @@ class OrVal(Valid):
           self.cata_info=""
           return 1
 
+      def has_into(self):
+          """
+          Dans le cas ou plusieurs validateurs sont reliés par un OU
+          il faut que tous les validateurs proposent un choix pour
+          qu'on considère que leur union propose un choix.
+          Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
+          En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
+          """
+          for validator in self.validators:
+              v=validator.has_into()
+              if not v :
+                 return 0
+          return 1
+
+      def get_into(self,liste_courante=None,into_courant=None):
+          """
+          Dans le cas ou plusieurs validateurs sont reliés par un OU
+          tous les validateurs doivent proposer un choix pour
+          qu'on considère que leur union propose un choix. Tous les choix
+          proposés par les validateurs sont réunis (opérateur d'union).
+          Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
+          En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un 
+          choix (1,2,3,4,5,6)       
+          """
+          validator_into=[]
+          for validator in self.validators:
+              v_into=validator.get_into(liste_courante,into_courant)
+              if v_into is None:
+                 return v_into
+              validator_into.extend(v_into)
+          return validator_into
+
+      def valide_liste_partielle(self,liste_courante=None):
+          """
+           Méthode de validation de liste partielle pour le validateur Or.
+           Si un des validateurs gérés par le validateur Or considère la
+           liste comme valide, le validateur Or la considère comme valide.
+          """
+          for validator in self.validators:
+              v=validator.valide_liste_partielle(liste_courante)
+              if v :
+                 return 1
+          return 0
+
 class AndVal(Valid):
       """
           Cette classe est un validateur qui controle une liste de validateurs
-          Elle verifie que tous les validateurs de la liste sont positifs
+          Elle verifie que tous les validateurs de la liste valident la valeur
       """
       def __init__(self,validators=()):
-          if type(validators) not in (types.ListType,types.TupleType): validators=(validators,)
+          if type(validators) not in (types.ListType,types.TupleType): 
+             validators=(validators,)
           self.validators=[]
           for validator in validators:
               if type(validator) == types.FunctionType:
@@ -424,7 +752,30 @@ class AndVal(Valid):
           self.cata_info=""
 
       def info(self):
-          return " et ".join([v.info() for v in self.validators])
+          return "\n et ".join([v.info() for v in self.validators])
+
+      def info_erreur_item(self):
+          chaine=""
+          a=1
+          for v in self.validators:
+              if v.info_erreur_item() != " " :
+                 if a==1:
+                    chaine=v.info_erreur_item()
+                    a=0
+                 else:
+                    chaine=chaine+" \n et "+v.info_erreur_item()
+          return chaine
+
+      def info_erreur_liste(self):
+          a=1
+          for v in self.validators:
+              if v.info_erreur_liste() != " " :
+                 if a==1:
+                    chaine=v.info_erreur_liste()
+                    a=0
+                 else:
+                    chaine=chaine+" \n et "+v.info_erreur_liste()
+          return chaine
 
       def verif(self,valeur):
           for validator in self.validators:
@@ -434,6 +785,15 @@ class AndVal(Valid):
                  return 0
           return 1
 
+      def verif_item(self,valeur):
+          for validator in self.validators:
+              v=validator.verif_item(valeur)
+              if not v :
+                 # L'info n'est probablement pas la meme que pour verif ???
+                 self.local_info=validator.info()
+                 return 0
+          return 1
+
       def verif_cata(self):
           infos=[]
           for validator in self.validators:
@@ -445,6 +805,62 @@ class AndVal(Valid):
           self.cata_info=""
           return 1
 
+      def valide_liste_partielle(self,liste_courante=None):
+          """
+           Méthode de validation de liste partielle pour le validateur And.
+           Tous les validateurs gérés par le validateur And doivent considérer
+           la liste comme valide, pour que le validateur And la considère
+           comme valide.
+          """
+          for validator in self.validators:
+              v=validator.valide_liste_partielle(liste_courante)
+              if not v :
+                 return 0
+          return 1
+
+      def is_list(self):
+          """
+          Si plusieurs validateurs sont reliés par un ET
+          il faut que tous les validateurs attendent une liste
+          pour qu'on considère que leur intersection attende une liste.
+          Exemple Range(2,5) ET Card(1) n'attend pas une liste
+          Range(2,5) ET Pair attend une liste
+          """
+          for validator in self.validators:
+              v=validator.is_list()
+              if v == 0 :
+                 return 0
+          return 1
+
+      def has_into(self):
+          """
+          Dans le cas ou plusieurs validateurs sont reliés par un ET
+          il suffit qu'un seul validateur propose un choix pour
+          qu'on considère que leur intersection propose un choix.
+          Exemple : Enum(1,2,3) ET entier pair, propose un choix
+          En revanche, entier pair ET superieur à 10 ne propose pas de choix
+          """
+          for validator in self.validators:
+              v=validator.has_into()
+              if v :
+                 return 1
+          return 0
+
+      def get_into(self,liste_courante=None,into_courant=None):
+          """
+          Dans le cas ou plusieurs validateurs sont reliés par un ET
+          il suffit qu'un seul validateur propose un choix pour
+          qu'on considère que leur intersection propose un choix. Tous les
+          choix proposés par les validateurs sont croisés (opérateur
+          d'intersection)
+          Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
+          En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
+          """
+          for validator in self.validators:
+              into_courant=validator.get_into(liste_courante,into_courant)
+              if into_courant in ([],None):break
+          return into_courant
+
 def do_liste(validators):
     """ 
        Convertit une arborescence de validateurs en OrVal ou AndVal