Salome HOME
bugs + translator
[tools/eficas.git] / Noyau / N_VALIDATOR.py
index fbd8cc5655818b846e027e81e460cb649c0a5ffa..4a7f3053cccd45efd50d3ce8e0c950e20b843b13 100644 (file)
@@ -1,21 +1,23 @@
-#@ MODIF N_VALIDATOR Noyau  DATE 16/05/2007   AUTEUR COURTOIS M.COURTOIS 
-# -*- coding: iso-8859-1 -*-
-#            CONFIGURATION MANAGEMENT OF EDF VERSION
-# ======================================================================
-# COPYRIGHT (C) 1991 - 2003  EDF R&D                  WWW.CODE-ASTER.ORG
-# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
-# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
-# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
-# (AT YOUR OPTION) ANY LATER VERSION.
+# coding=utf-8
+# Copyright (C) 2007-2015   EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
 #
 #
-# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
-# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
-# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
-# GENERAL PUBLIC LICENSE FOR MORE DETAILS.
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 #
 #
-# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
-# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
-#    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
 # ======================================================================
 
 """
 # ======================================================================
 
 """
    implanter le concept de validateur dans Accas
 """
 import types
    implanter le concept de validateur dans Accas
 """
 import types
-import string
 import traceback
 import traceback
+import re
 from N_ASSD import ASSD
 from N_ASSD import ASSD
+from N_types import is_int, is_float_or_int, is_complex, is_number, is_str, is_sequence
+from strfunc import convert, ufmt
+from Extensions.i18n import tr
+
+
+
+class ValError(Exception):
+    pass
 
 
-class ValError(Exception):pass
 
 def cls_mro(cls):
 
 def cls_mro(cls):
-    if hasattr(cls,"__mro__"):return cls.__mro__
-    mro=[cls]
+    if hasattr(cls, "__mro__"):
+        return cls.__mro__
+    mro = [cls]
     for base in cls.__bases__:
         mro.extend(cls_mro(base))
     return mro
 
     for base in cls.__bases__:
         mro.extend(cls_mro(base))
     return mro
 
+
 class Protocol:
 class Protocol:
-    def __init__(self,name):
+
+    def __init__(self, name):
         self.registry = {}
         self.name = name
         self.registry = {}
         self.name = name
-        self.args={}
+        self.args = {}
 
     def register(self, T, A):
         self.registry[T] = A
 
     def register(self, T, A):
         self.registry[T] = A
@@ -49,99 +61,146 @@ class Protocol:
         # (a) verifier si l'objet peut s'adapter au protocole
         adapt = getattr(obj, '__adapt__', None)
         if adapt is not None:
         # (a) verifier si l'objet peut s'adapter au protocole
         adapt = getattr(obj, '__adapt__', None)
         if adapt is not None:
-            # on demande à l'objet obj de réaliser lui-meme l'adaptation
+            # on demande à l'objet obj de réaliser lui-meme l'adaptation
             return adapt(self)
 
             return adapt(self)
 
-        # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
+        # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
         if self.registry:
             for T in cls_mro(obj.__class__):
                 if T in self.registry:
         if self.registry:
             for T in cls_mro(obj.__class__):
                 if T in self.registry:
-                    return self.registry[T](obj,self,**self.args)
+                    return self.registry[T](obj, self, **self.args)
 
         # (c) utiliser l'adapteur par defaut
 
         # (c) utiliser l'adapteur par defaut
-        return self.default(obj,**self.args)
+        return self.default(obj, **self.args)
 
 
-    def default(self,obj,**args):
+    def default(self, obj, **args):
         raise TypeError("Can't adapt %s to %s" %
                         (obj.__class__.__name__, self.name))
 
         raise TypeError("Can't adapt %s to %s" %
                         (obj.__class__.__name__, self.name))
 
+
 class PProtocol(Protocol):
 class PProtocol(Protocol):
-    """Verificateur de protocole paramétré (classe de base)"""
-    #Protocole paramétré. Le registre est unique pour toutes les instances. La methode register est une methode de classe
-    registry={}
-    def __init__(self,name,**args):
+
+    """Verificateur de protocole paramétré (classe de base)"""
+    # Protocole paramétré. Le registre est unique pour toutes les instances.
+    # La methode register est une methode de classe
+    registry = {}
+
+    def __init__(self, name, **args):
         self.name = name
         self.name = name
-        self.args=args
+        self.args = args
+
     def register(cls, T, A):
         cls.registry[T] = A
     def register(cls, T, A):
         cls.registry[T] = A
-    register=classmethod(register)
+    register = classmethod(register)
+
 
 class ListProtocol(Protocol):
 
 class ListProtocol(Protocol):
-    """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
-    def default(self,obj):
-        if type(obj) == types.TupleType :
-            if obj[0] in ('RI','MP'):
-                #il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
+
+    """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
+
+    def default(self, obj):
+        if type(obj) is tuple:
+            if len(obj) > 0 and obj[0] in ('RI', 'MP'):
+                # il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
                 return (obj,)
             else:
                 return obj
                 return (obj,)
             else:
                 return obj
-        elif type(obj) == types.ListType :
+        elif type(obj) is list:
             return obj
             return obj
-        elif obj == None :
+        elif obj == None:
             # pas de valeur affecte. La cardinalite vaut 0
             return obj
             # pas de valeur affecte. La cardinalite vaut 0
             return obj
-        elif type(obj) == types.StringType :
-            #il s'agit d'une chaine. La cardinalite vaut 1
+        elif is_str(obj):
+            # il s'agit d'une chaine. La cardinalite vaut 1
             return (obj,)
         else:
             try:
                 # si l'objet supporte len, on a la cardinalite
             return (obj,)
         else:
             try:
                 # si l'objet supporte len, on a la cardinalite
-                length=len(obj)
+                length = len(obj)
                 return obj
             except:
                 # sinon elle vaut 1
                 return (obj,)
 
                 return obj
             except:
                 # sinon elle vaut 1
                 return (obj,)
 
-listProto=ListProtocol("list")
+listProto = ListProtocol("list")
+
 
 class TypeProtocol(PProtocol):
 
 class TypeProtocol(PProtocol):
+
     """Verificateur de type parmi une liste de types possibles"""
     """Verificateur de type parmi une liste de types possibles"""
-    #pas de registre par instance. Registre unique pour toutes les instances de TypeProtocol
-    registry={}
-    def __init__(self,name,typ=None):
-        PProtocol.__init__(self,name,typ=typ)
-        self.typ=typ
+    # pas de registre par instance. Registre unique pour toutes les instances
+    # de TypeProtocol
+    registry = {}
+
+    def __init__(self, name, typ=None):
+        PProtocol.__init__(self, name, typ=typ)
+        self.typ = typ
+
+    def default(self, obj, typ):
 
 
-    def default(self,obj,typ):
+        err = ""
         for type_permis in typ:
             if type_permis == 'R':
         for type_permis in typ:
             if type_permis == 'R':
-                if type(obj) in (types.IntType,types.FloatType,types.LongType):return obj
+                if is_float_or_int(obj):
+                    return obj
             elif type_permis == 'I':
             elif type_permis == 'I':
-                if type(obj) in (types.IntType,types.LongType):return obj
+                if is_int(obj):
+                    return obj
             elif type_permis == 'C':
             elif type_permis == 'C':
-                if self.is_complexe(obj):return obj
+                if self.is_complexe(obj):
+                    return obj
             elif type_permis == 'TXM':
             elif type_permis == 'TXM':
-                if type(obj)==types.StringType:return obj
+                if is_str(obj):
+                    return obj
             elif type_permis == 'shell':
             elif type_permis == 'shell':
-                if type(obj)==types.StringType:return obj
-            elif type(type_permis) == types.ClassType or isinstance(type_permis,type):
-                if self.is_object_from(obj,type_permis):return obj
-            elif type(type_permis) == types.InstanceType or isinstance(type_permis,object):
+                if is_str(obj):
+                    return obj
+            elif type_permis == 'Fichier':
+                import os
+                if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj):
+                    return obj
+                else:
+                    raise ValError(
+                        ufmt(_(tr(u"%s n'est pas un fichier valide")), repr(obj)))
+            elif type_permis == 'FichierNoAbs':
+                import os
+                if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")):
+                    return obj
+                else:
+                    raise ValError(
+                        ufmt(_(tr("%s n'est pas un fichier valide")), repr(obj)))
+            elif type_permis == 'Repertoire':
+                import os
+                if os.path.isdir(obj):
+                    return obj
+                else:
+                    raise ValError(
+                        ufmt(_(tr(u"%s n'est pas un repertoire valide")), repr(obj)))
+            elif type(type_permis) == types.ClassType or isinstance(type_permis, type):
                 try:
                 try:
-                    if type_permis.__convert__(obj) : return obj
-                except:
+                    if self.is_object_from(obj, type_permis):
+                        return obj
+                except Exception, err:
+                    pass
+            elif type(type_permis) == types.InstanceType or isinstance(type_permis, object):
+                try:
+                    if type_permis.__convert__(obj):
+                        return obj
+                except Exception, err:
                     pass
             else:
                     pass
             else:
-                print "Type non encore géré %s" %`type_permis`
-
-        raise ValError("%s n'est pas d'un type autorisé: %s" % (repr(obj),typ))
+                print convert(ufmt(_(tr(u"Type non encore gere %s")), `type_permis`))
+        raise ValError(
+            ufmt(_(tr(u"%s (de type %s) n'est pas d'un type autorise: %s %s")),
+                 repr(obj), type(obj), typ, unicode(err)))
 
 
-    def is_complexe(self,valeur):
+    def is_complexe(self, valeur):
         """ Retourne 1 si valeur est un complexe, 0 sinon """
         """ Retourne 1 si valeur est un complexe, 0 sinon """
-        if type(valeur) in (types.ComplexType,types.IntType,types.FloatType,types.LongType):
-            # Pour permettre l'utilisation de complexes Python
+        if is_number(valeur):
+            # Pour permettre l'utilisation de complexes Python (accepte les
+            # entiers et réels)
             return 1
             return 1
-        elif type(valeur) != types.TupleType :
+        elif type(valeur) != tuple:
             # On n'autorise pas les listes pour les complexes
             return 0
         elif len(valeur) != 3:
             # On n'autorise pas les listes pour les complexes
             return 0
         elif len(valeur) != 3:
@@ -149,16 +208,16 @@ class TypeProtocol(PProtocol):
         else:
             # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
             # valeur suivie de 2 reels.
         else:
             # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
             # valeur suivie de 2 reels.
-            if string.strip(valeur[0]) in ('RI','MP'):
+            if valeur[0].strip() in ('RI', 'MP'):
                 try:
                 try:
-                    v1=reelProto.adapt(valeur[1]),reelProto.adapt(valeur[2])
+                    v1 = reelProto.adapt(valeur[1]), reelProto.adapt(valeur[2])
                     return 1
                 except:
                     return 0
             else:
                 return 0
 
                     return 1
                 except:
                     return 0
             else:
                 return 0
 
-    def is_object_from(self,objet,classe):
+    def is_object_from(self, objet, classe):
         """
            Retourne 1 si objet est une instance de la classe classe, 0 sinon
         """
         """
            Retourne 1 si objet est une instance de la classe classe, 0 sinon
         """
@@ -166,916 +225,1159 @@ class TypeProtocol(PProtocol):
         if convert is not None:
             # classe verifie les valeurs
             try:
         if convert is not None:
             # classe verifie les valeurs
             try:
-                v convert(objet)
+                v = convert(objet)
                 return v is not None
                 return v is not None
+            except ValueError, err:
+                raise
             except:
                 return 0
         # On accepte les instances de la classe et des classes derivees
             except:
                 return 0
         # On accepte les instances de la classe et des classes derivees
-        return isinstance(objet,classe)
+        return isinstance(objet, classe)
+
+reelProto = TypeProtocol("reel", typ=('R',))
 
 
-reelProto=TypeProtocol("reel",typ=('R',))
 
 class CardProtocol(PProtocol):
 
 class CardProtocol(PProtocol):
-    """Verificateur de cardinalité """
-    #pas de registre par instance. Registre unique pour toutes les instances
-    registry={}
-    def __init__(self,name,min=1,max=1):
-        PProtocol.__init__(self,name,min=min,max=max)
-
-    def default(self,obj,min,max):
-        length=len(obj)
-        if length < min or length >max:
-            raise ValError("Nombre d'arguments de %s incorrect (min = %s, max = %s)" % (repr(obj),min,max) )
+
+    """Verificateur de cardinalité """
+    # pas de registre par instance. Registre unique pour toutes les instances
+    registry = {}
+
+    def __init__(self, name, min=1, max=1):
+        PProtocol.__init__(self, name, min=min, max=max)
+
+    def default(self, obj, min, max):
+        length = len(obj)
+        if length < min or length > max:
+            raise ValError(
+                ufmt(
+                    _(tr(u"Nombre d'arguments de %s incorrect (min = %s, max = %s)")),
+                    repr(obj), min, max))
         return obj
 
         return obj
 
+
 class IntoProtocol(PProtocol):
 class IntoProtocol(PProtocol):
-    """Verificateur de choix possibles : liste discrète ou intervalle"""
-    #pas de registre par instance. Registre unique pour toutes les instances
-    registry={}
-    def __init__(self,name,into=None,val_min='**',val_max='**'):
-        PProtocol.__init__(self,name,into=into,val_min=val_min,val_max=val_max)
-        self.val_min=val_min
-        self.val_max=val_max
-
-    def default(self,obj,into,val_min,val_max):
+
+    """Verificateur de choix possibles : liste discrète ou intervalle"""
+    # pas de registre par instance. Registre unique pour toutes les instances
+    registry = {}
+
+    def __init__(self, name, into=None, val_min='**', val_max='**'):
+        PProtocol.__init__(
+            self, name, into=into, val_min=val_min, val_max=val_max)
+        self.val_min = val_min
+        self.val_max = val_max
+
+    def default(self, obj, into, val_min, val_max):
         if into:
             if obj not in into:
         if into:
             if obj not in into:
-                raise ValError("La valeur : %s  ne fait pas partie des choix possibles %s" % (repr(obj),into) )
+                raise ValError(
+                    ufmt(
+                        _(tr(u"La valeur : %s  ne fait pas partie des choix possibles %s")), repr(obj), into))
         else:
         else:
-            #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
-            if type(obj) in (types.IntType,types.FloatType,types.LongType) :
-                if val_min == '**': val_min = obj -1
-                if val_max == '**': val_max = obj +1
-                if obj < val_min or obj > val_max :
-                    raise ValError("La valeur : %s est en dehors du domaine de validité [ %s , %s ]" % (repr(obj),self.val_min,self.val_max) )
+            # on est dans le cas d'un ensemble continu de valeurs possibles
+            # (intervalle)
+            if is_float_or_int(obj):
+                if val_min == '**':
+                    val_min = obj - 1
+                if val_max == '**':
+                    val_max = obj + 1
+                if obj < val_min or obj > val_max:
+                    raise ValError(
+                        ufmt(
+                            _(tr(u"La valeur : %s est en dehors du domaine de validite [ %s , %s ]")),
+                            repr(obj), self.val_min, self.val_max))
         return obj
 
         return obj
 
-class MinStr:
-    #exemple de classe pour verificateur de type
-    #on utilise des instances de classe comme type (typ=MinStr(3,6), par exemple)
-    def __init__(self,min,max):
-        self.min=min
-        self.max=max
 
 
-    def __convert__(self,valeur):
-        if type(valeur) == types.StringType and self.min <= len(valeur) <= self.max:return valeur
-        raise ValError("%s n'est pas une chaine de longueur comprise entre %s et %s" % (valeur,self.min,self.max))
+class MinStr:
+    # exemple de classe pour verificateur de type
+    # on utilise des instances de classe comme type (typ=MinStr(3,6), par
+    # exemple)
+
+    def __init__(self, min, max):
+        self.min = min
+        self.max = max
+
+    def __convert__(self, valeur):
+        if is_str(valeur) and self.min <= len(valeur) <= self.max:
+            return valeur
+        raise ValError(
+            ufmt(
+                _(tr(u"%s n'est pas une chaine de longueur comprise entre %s et %s")),
+                valeur, self.min, self.max))
 
     def __repr__(self):
 
     def __repr__(self):
-        return "TXM de longueur entre %s et %s" %(self.min,self.max)
+        return ufmt(_(tr(u"TXM de longueur entre %s et %s")), self.min, self.max)
+
 
 class Valid(PProtocol):
 
 class Valid(PProtocol):
-   """
-        Cette classe est la classe mere des validateurs Accas
-        Elle doit etre derivee
-        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}
-   """
-   registry={}
-   def __init__(self,**args):
-       PProtocol.__init__(self,"valid",**args)
-
-   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
-           comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
-           (valide) sinon 0 (invalide).
-
-           @type valeur: tout type python
-           @param valeur: valeur du mot cle a valider
-           @rtype: C{boolean}
-           @return: indicateur de validite 1 (valide) ou 0 (invalide)
-       """
-       raise "Must be implemented"
-
-   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.
-           Elle est facultative et retourne 1 (valide) par defaut.
-           Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
-           parametres de definition ne sont pas corrects.
-           La raison de l'invalidite est stockee dans l'attribut cata_info.
-
-           @rtype: C{boolean}
-           @return: indicateur de validite 1 (valide) ou 0 (invalide)
-       """
-       return 1
-
-   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
+
+    """
+         Cette classe est la classe mere des validateurs Accas
+         Elle doit etre derivee
+         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}
+    """
+    registry = {}
+
+    def __init__(self, **args):
+        PProtocol.__init__(self, "valid", **args)
+
+    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 _(u"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
+            comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
+            (valide) sinon 0 (invalide).
+
+            @type valeur: tout type python
+            @param valeur: valeur du mot cle a valider
+            @rtype: C{boolean}
+            @return: indicateur de validite 1 (valide) ou 0 (invalide)
+        """
+        raise NotImplementedError("Must be implemented")
+
+    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.
+            Elle est facultative et retourne 1 (valide) par defaut.
+            Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
+            parametres de definition ne sont pas corrects.
+            La raison de l'invalidite est stockee dans l'attribut cata_info.
+
+            @rtype: C{boolean}
+            @return: indicateur de validite 1 (valide) ou 0 (invalide)
+        """
+        return 1
+
+    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
+
 
 class ListVal(Valid):
 
 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 convert(self,valeur):
-       """
-          Méthode convert pour les validateurs de listes. Cette méthode
-          fait appel à la méthode convert_item sur chaque élément de la
-          liste.
-       """
-       if type(valeur) in (types.ListType,types.TupleType):
-          for val in valeur:
-              self.convert_item(val)
-          return valeur
-       else:
-          return self.convert_item(valeur)
-
-   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 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)
+
+    """
+        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 convert(self, valeur):
+        """
+           Méthode convert pour les validateurs de listes. Cette méthode
+           fait appel à la méthode convert_item sur chaque élément de la
+           liste.
+        """
+        if is_sequence(valeur):
+            for val in valeur:
+                self.convert_item(val)
+            return valeur
+        else:
+            return self.convert_item(valeur)
+
+    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 is_sequence(valeur):
+            for val in valeur:
+                if not self.verif_item(val):
+                    return 0
+            return 1
+        else:
+            return self.verif_item(valeur)
+
 
 class Compulsory(ListVal):
 
 class Compulsory(ListVal):
-      """
-          Validateur operationnel
-          Verification de la présence obligatoire d'un élément dans une liste
-      """
-      registry={}
-      def __init__(self,elem=()):
-          if type(elem) not in (types.ListType,types.TupleType): elem=(elem,)
-          Valid.__init__(self,elem=elem)
-          self.elem=elem
-          self.cata_info=""
-
-      def info(self):
-          return "valeur %s obligatoire" % `self.elem`
-
-      def default(self,valeur,elem):
-          return valeur
-
-      def verif_item(self,valeur):
-          return 1
-
-      def convert(self,valeur):
-          elem=list(self.elem)
-          for val in valeur:
-              v=self.adapt(val)
-              if v in elem:elem.remove(v)
-          if elem:
-              raise ValError("%s ne contient pas les elements obligatoires : %s " %(valeur,elem))
-          return valeur
-
-      def has_into(self):
-          return 1
-
-      def verif(self,valeur):
-          if type(valeur) not in (types.ListType,types.TupleType):
-             liste=list(valeur)
-          else:
-             liste=valeur
-          for val in self.elem :
-             if val not in liste : return 0
-          return 1
-
-      def info_erreur_item(self):
-          return "La valeur n'est pas dans la liste des choix possibles"
+    """
+        Validateur operationnel
+        Verification de la présence obligatoire d'un élément dans une liste
+    """
+    registry = {}
+
+    def __init__(self, elem=()):
+        if not is_sequence(elem):
+            elem = (elem,)
+        Valid.__init__(self, elem=elem)
+        self.elem = elem
+        self.cata_info = ""
+
+    def info(self):
+        return ufmt(_(tr(u"valeur %s obligatoire")), `self.elem`)
+
+    def default(self, valeur, elem):
+        return valeur
+
+    def verif_item(self, valeur):
+        return 1
+
+    def convert(self, valeur):
+        elem = list(self.elem)
+        for val in valeur:
+            v = self.adapt(val)
+            if v in elem:
+                elem.remove(v)
+        if elem:
+            raise ValError(
+                ufmt(_(tr(u"%s ne contient pas les elements obligatoires : %s ")),
+                     valeur, elem))
+        return valeur
+
+    def has_into(self):
+        return 1
+
+    def verif(self, valeur):
+        if not is_sequence(valeur):
+            liste = list(valeur)
+        else:
+            liste = valeur
+        for val in self.elem:
+            if val not in liste:
+                return 0
+        return 1
+
+    def info_erreur_item(self):
+        return _(u"La valeur n'est pas dans la liste des choix possibles")
+
+
+class Together(ListVal):
+    """
+        Validateur operationnel
+        si un des éléments est présent les autres doivent aussi l'être
+    """
+    registry = {}
+
+    def __init__(self, elem=()):
+        if not is_sequence(elem):
+            elem = (elem,)
+        Valid.__init__(self, elem=elem)
+        self.elem = elem
+        self.cata_info = ""
+
+    def info(self):
+        return ufmt(_(tr(u"%s present ensemble")), `self.elem`)
+
+    def default(self, valeur, elem):
+        return valeur
+
+    def verif_item(self, valeur):
+        return 1
+
+    def convert(self, valeur):
+        elem = list(self.elem)
+        for val in valeur:
+            v = self.adapt(val)
+            if v in elem: elem.remove(v)
+        if ( len(elem) == 0 ): return valeur
+        if len(elem) != len(list(self.elem)) :
+            raise ValError( ufmt(_(tr(u"%s ne contient pas les elements devant etre presents ensemble: %s ")), valeur, elem))
+        return valeur
+
+    def has_into(self):
+        return 1
+
+    def verif(self, valeur):
+        if not is_sequence(valeur):
+            liste = list(valeur)
+        else:
+            liste = valeur
+        compte = 0
+        for val in self.elem:
+            if val in liste: compte += 1
+        if ( compte == 0 ): return 1
+        if ( compte != len( list(self.elem) ) ): return 0
+        return 1
+
+    def info_erreur_item(self):
+        return _(u"La valeur n'est pas dans la liste des choix possibles")
+
+
+class Absent(ListVal):
+    """
+        Validateur operationnel
+        si un des éléments est présent non valide
+    """
+    registry = {}
+
+    def __init__(self, elem=()):
+        if not is_sequence(elem):
+            elem = (elem,)
+        Valid.__init__(self, elem=elem)
+        self.elem = elem
+        self.cata_info = ""
+
+    def info(self):
+        return ufmt(_(tr(u"%s absent")), `self.elem`)
+
+    def default(self, valeur, elem):
+        return valeur
+
+    def verif_item(self, valeur):
+        return 1
+
+    def convert(self, valeur):
+        elem = list(self.elem)
+        for val in valeur:
+            v = self.adapt(val)
+            if v in elem:
+                raise ValError( ufmt(_(tr(u"%s n'est pas autorise : %s ")), v, elem))
+        return valeur
+
+    def has_into(self):
+        return 1
+
+    def verif(self, valeur):
+        if not is_sequence(valeur):
+            liste = list(valeur)
+        else:
+            liste = valeur
+        for val in self.elem:
+            if val in liste: return 0
+        return 1
+
+    def info_erreur_item(self):
+        return _(u"La valeur n'est pas dans la liste des choix possibles")
+
 
 class NoRepeat(ListVal):
 
 class NoRepeat(ListVal):
-      """
-          Validateur operationnel
-          Verification d'absence de doublons dans la liste.
-      """
-      def __init__(self):
-          Valid.__init__(self)
-          self.cata_info=""
-
-      def info(self):
-          return ": pas de présence de doublon dans la liste"
-
-      def info_erreur_liste(self):
-          return "Les doublons ne sont pas permis"
-
-      def default(self,valeur):
-          if valeur in self.liste : raise ValError("%s est un doublon" % valeur)
-          return valeur
-
-      def convert(self,valeur):
-          self.liste=[]
-          for val in valeur:
-              v=self.adapt(val)
-              self.liste.append(v)
-          return valeur
-
-      def verif_item(self,valeur):
-          return 1
-
-      def verif(self,valeur):
-          if type(valeur) in (types.ListType,types.TupleType):
-             liste=list(valeur)
-             for val in liste:
-                if liste.count(val)!=1 : return 0
-             return 1
-          else:
-             return 1
-
-      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
+    """
+        Validateur operationnel
+        Verification d'absence de doublons dans la liste.
+    """
+    def __init__(self):
+        Valid.__init__(self)
+        self.cata_info = ""
+
+    def info(self):
+        return _(u"Pas de doublon dans la liste")
+
+    def info_erreur_liste(self):
+        return _(u"Les doublons ne sont pas permis")
+
+    def default(self, valeur):
+        if valeur in self.liste:
+            raise ValError(ufmt(_(tr(u"%s est un doublon")), valeur))
+        return valeur
+
+    def convert(self, valeur):
+        self.liste = []
+        for val in valeur:
+            v = self.adapt(val)
+            self.liste.append(v)
+        return valeur
+
+    def verif_item(self, valeur):
+        return 1
+
+    def verif(self, valeur):
+        if is_sequence(valeur):
+            liste = list(valeur)
+            for val in liste:
+                if liste.count(val) != 1:
+                    return 0
+            return 1
+        else:
+            return 1
+
+    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):
 
 class LongStr(ListVal):
-      """
-          Validateur operationnel
-          Verification de la longueur d une chaine
-      """
-      def __init__(self,low,high):
-          ListVal.__init__(self,low=low,high=high)
-          self.low=low
-          self.high=high
-          self.cata_info=""
-
-      def info(self):
-          return "longueur de la chaine entre %s et %s" %(self.low,self.high)
-
-      def info_erreur_item(self):
-          return "Longueur de la chaine incorrecte"
-
-      def convert(self,valeur):
-          for val in valeur:
-              v=self.adapt(val)
-          return valeur
-
-      def verif_item(self,valeur):
-          try:
-             self.adapt(valeur)
-             return 1
-          except:
-             return 0
-
-      def default(self,valeur,low,high):
-          if type(valeur) != types.StringType :
-             raise ValError("%s n'est pas une string" % repr(valeur))
-          if valeur[0]=="'" and valeur[-1]=="'" :
-             low=low+2
-             high=high+2
-          if len(valeur) < low or len(valeur) > high :
-             raise ValError("%s n'est pas de la bonne longueur" % repr(valeur))
-          return valeur
+
+    """
+        Validateur operationnel
+        Verification de la longueur d une chaine
+    """
+
+    def __init__(self, low, high):
+        ListVal.__init__(self, low=low, high=high)
+        self.low = low
+        self.high = high
+        self.cata_info = ""
+
+    def info(self):
+        return ufmt(_(tr(u"longueur de la chaine entre %s et %s")), self.low, self.high)
+
+    def info_erreur_item(self):
+        return _(tr(u"Longueur de la chaine incorrecte"))
+
+    def convert(self, valeur):
+        for val in valeur:
+            v = self.adapt(val)
+        return valeur
+
+    def verif_item(self, valeur):
+        try:
+            self.adapt(valeur)
+            return 1
+        except:
+            return 0
+
+    def default(self, valeur, low, high):
+        if not is_str(valeur):
+            raise ValError(ufmt(_(tr(u"%s n'est pas une chaine")), repr(valeur)))
+        if valeur[0] == "'" and valeur[-1] == "'":
+            low = low + 2
+            high = high + 2
+        if len(valeur) < low or len(valeur) > high:
+            raise ValError(
+                ufmt(_(tr(u"%s n'est pas de la bonne longueur")), repr(valeur)))
+        return valeur
+
+
+class OnlyStr(ListVal):
+
+    """
+        Validateur operationnel
+        Valide que c'est une chaine
+    """
+
+    def __init__(self):
+        ListVal.__init__(self)
+        self.cata_info = ""
+
+    def info(self):
+        return _(u"regarde si c'est une chaine")
+
+    def info_erreur_item(self):
+        return _(u"Ce n'est pas une chaine")
+
+    def convert(self, valeur):
+        for val in valeur:
+            v = self.adapt(val)
+        return valeur
+
+    def verif_item(self, valeur):
+        try:
+            self.adapt(valeur)
+            return 1
+        except:
+            return 0
+
+    def default(self, valeur):
+        if not is_str(valeur):
+            raise ValError(ufmt(_(tr(u"%s n'est pas une chaine")), repr(valeur)))
+        return valeur
+
 
 class OrdList(ListVal):
 
 class OrdList(ListVal):
-      """
-          Validateur operationnel
-          Verification qu'une liste est croissante ou decroissante
-      """
-      def __init__(self,ord):
-          ListVal.__init__(self,ord=ord)
-          self.ord=ord
-          self.cata_info=""
-
-      def info(self):
-          return "liste %s" % self.ord
-
-      def info_erreur_liste(self) :
-          return "La liste doit etre en ordre "+self.ord
-
-      def convert(self,valeur):
-          self.val=None
-          self.liste=valeur
-          for v in valeur:
-              self.adapt(v)
-          return valeur
-
-      def default(self,valeur,ord):
-          if self.ord=='croissant':
-              if self.val is not None and valeur<self.val:
-                  raise ValError("%s n'est pas par valeurs croissantes" % repr(self.liste))
-          elif self.ord=='decroissant':
-              if self.val is not None and valeur > self.val:
-                  raise ValError("%s n'est pas par valeurs decroissantes" % repr(self.liste))
-          self.val=valeur
-          return valeur
-
-      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
+
+    """
+        Validateur operationnel
+        Verification qu'une liste est croissante ou decroissante
+    """
+
+    def __init__(self, ord):
+        ListVal.__init__(self, ord=ord)
+        self.ord = ord
+        self.cata_info = ""
+
+    def info(self):
+        return ufmt(_(tr(u"liste %s")), self.ord)
+
+    def info_erreur_liste(self):
+        return ufmt(_(tr(u"La liste doit etre en ordre %s")), self.ord)
+
+    def convert(self, valeur):
+        self.val = None
+        self.liste = valeur
+        for v in valeur:
+            self.adapt(v)
+        return valeur
+
+    def default(self, valeur, ord):
+        if self.ord == 'croissant':
+            if self.val is not None and valeur < self.val:
+                raise ValError(
+                    ufmt(_(tr(u"%s n'est pas par valeurs croissantes")), repr(self.liste)))
+        elif self.ord == 'decroissant':
+            if self.val is not None and valeur > self.val:
+                raise ValError(
+                    ufmt(_(tr(u"%s n'est pas par valeurs decroissantes")), repr(self.liste)))
+        self.val = valeur
+        return valeur
+
+    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
+
 
 class OrVal(Valid):
 
 class OrVal(Valid):
-      """
-          Validateur operationnel
-          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
-      """
-      def __init__(self,validators=()):
-          if type(validators) not in (types.ListType,types.TupleType):
-             validators=(validators,)
-          self.validators=[]
-          for validator in validators:
-              if type(validator) == types.FunctionType:
-                 self.validators.append(FunctionVal(validator))
-              else:
-                 self.validators.append(validator)
-          self.cata_info=""
-
-      def info(self):
-          return "\n ou ".join([v.info() for v in self.validators])
-
-      def convert(self,valeur):
-          for validator in self.validators:
-              try:
-                 return validator.convert(valeur)
-              except:
-                 pass
-          raise ValError("%s n'est pas du bon type" % repr(valeur))
-
-      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)
-              if v :
-                 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:
-              v=validator.verif_cata()
-              if not v :infos.append(validator.cata_info)
-          if infos:
-             self.cata_info="\n".join(infos)
-             return 0
-          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
+
+    """
+        Validateur operationnel
+        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
+    """
+
+    def __init__(self, validators=()):
+        if not is_sequence(validators):
+            validators = (validators,)
+        self.validators = []
+        for validator in validators:
+            if type(validator) == types.FunctionType:
+                self.validators.append(FunctionVal(validator))
+            else:
+                self.validators.append(validator)
+        self.cata_info = ""
+
+    def info(self):
+        return "\n ou ".join([v.info() for v in self.validators])
+
+    def convert(self, valeur):
+        for validator in self.validators:
+            try:
+                return validator.convert(valeur)
+            except:
+                pass
+        raise ValError(ufmt(_(tr(u"%s n'est pas du bon type")), repr(valeur)))
+
+    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)
+            if v:
+                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:
+            v = validator.verif_cata()
+            if not v:
+                infos.append(validator.cata_info)
+        if infos:
+            self.cata_info = "\n".join(infos)
+            return 0
+        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):
 
 class AndVal(Valid):
-      """
-          Validateur operationnel
-          Cette classe est un validateur qui controle une liste de validateurs
-          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,)
-          self.validators=[]
-          for validator in validators:
-              if type(validator) == types.FunctionType:
-                 self.validators.append(FunctionVal(validator))
-              else:
-                 self.validators.append(validator)
-          self.cata_info=""
-
-      def info(self):
-          return "\n et ".join([v.info() for v in self.validators])
-
-      def convert(self,valeur):
-          for validator in self.validators:
-              valeur=validator.convert(valeur)
-          return valeur
-
-      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:
-              v=validator.verif(valeur)
-              if not v :
-                 self.local_info=validator.info()
-                 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:
-              v=validator.verif_cata()
-              if not v :infos.append(validator.cata_info)
-          if infos:
-             self.cata_info="\n".join(infos)
-             return 0
-          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
+
+    """
+        Validateur operationnel
+        Cette classe est un validateur qui controle une liste de validateurs
+        Elle verifie que tous les validateurs de la liste valident la valeur
+    """
+
+    def __init__(self, validators=()):
+        if not is_sequence(validators):
+            validators = (validators,)
+        self.validators = []
+        for validator in validators:
+            if type(validator) == types.FunctionType:
+                self.validators.append(FunctionVal(validator))
+            else:
+                self.validators.append(validator)
+            if hasattr(validator, 'fonctions'):
+                for fonction in validator.fonctions:
+                    f = getattr(validator, fonction)
+                    setattr(self, fonction, f)
+        self.cata_info = ""
+
+    def info(self):
+        return "\n et ".join([v.info() for v in self.validators])
+
+    def convert(self, valeur):
+        for validator in self.validators:
+            valeur = validator.convert(valeur)
+        return valeur
+
+    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):
+        chaine=""
+        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:
+            v = validator.verif(valeur)
+            if not v:
+                self.local_info = validator.info()
+                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:
+            v = validator.verif_cata()
+            if not v:
+                infos.append(validator.cata_info)
+        if infos:
+            self.cata_info = "\n".join(infos)
+            return 0
+        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
        validators est une liste de validateurs ou de listes ou de tuples
     """
 
 def do_liste(validators):
     """
        Convertit une arborescence de validateurs en OrVal ou AndVal
        validators est une liste de validateurs ou de listes ou de tuples
     """
-    valids=[]
+    valids = []
     for validator in validators:
         if type(validator) == types.FunctionType:
     for validator in validators:
         if type(validator) == types.FunctionType:
-           valids.append(FunctionVal(validator))
-        elif type(validator) == types.TupleType:
-           valids.append(OrVal(do_liste(validator)))
-        elif type(validator) == types.ListType:
-           valids.append(AndVal(do_liste(validator)))
+            valids.append(FunctionVal(validator))
+        elif type(validator) is tuple:
+            valids.append(OrVal(do_liste(validator)))
+        elif type(validator) is list:
+            valids.append(AndVal(do_liste(validator)))
         else:
         else:
-           valids.append(validator)
+            valids.append(validator)
     return valids
 
     return valids
 
+
 def validatorFactory(validator):
     if type(validator) == types.FunctionType:
 def validatorFactory(validator):
     if type(validator) == types.FunctionType:
-       return FunctionVal(validator)
-    elif type(validator) == types.TupleType:
-       return OrVal(do_liste(validator))
-    elif type(validator) == types.ListType:
-       return AndVal(do_liste(validator))
+        return FunctionVal(validator)
+    elif type(validator) is tuple:
+        return OrVal(do_liste(validator))
+    elif type(validator) is list:
+        return AndVal(do_liste(validator))
     else:
     else:
-       return validator
+        return validator
+
+# Ci-dessous : exemples de validateur (peu testés)
 
 
-# Ci-dessous : exemples de validateur (peu testés)
 
 class RangeVal(ListVal):
 
 class RangeVal(ListVal):
-      """
-          Exemple de classe validateur : verification qu'une valeur
-          est dans un intervalle.
-          Pour une liste on verifie que tous les elements sont
-          dans l'intervalle
-          Susceptible de remplacer les attributs "vale_min" "vale_max"
-          dans les catalogues
-      """
-      def __init__(self,low,high):
-          self.low=low
-          self.high=high
-          self.cata_info="%s doit etre inferieur a %s" %(low,high)
-
-      def info(self):
-          return "valeur dans l'intervalle %s , %s" %(self.low,self.high)
-
-      def convert_item(self,valeur):
-          if valeur > self.low and valeur < self.high:return valeur
-          raise ValError("%s devrait etre comprise entre %s et %s" %(valeur,self.low,self.high))
-
-      def verif_item(self,valeur):
-          return valeur > self.low and valeur < self.high
-
-      def info_erreur_item(self) :
-          return "La valeur doit etre comprise entre %s et %s" % (self.low,
-                                                                  self.high)
-
-      def verif_cata(self):
-          if self.low > self.high : return 0
-          return 1
+
+    """
+        Exemple de classe validateur : verification qu'une valeur
+        est dans un intervalle.
+        Pour une liste on verifie que tous les elements sont
+        dans l'intervalle
+        Susceptible de remplacer les attributs "vale_min" "vale_max"
+        dans les catalogues
+    """
+
+    def __init__(self, low, high):
+        self.low = low
+        self.high = high
+        self.cata_info = ufmt(_(tr(u"%s doit etre inferieur a %s")), low, high)
+
+    def info(self):
+        return ufmt(_(tr(u"valeur dans l'intervalle %s , %s")), self.low, self.high)
+
+    def convert_item(self, valeur):
+        if valeur > self.low and valeur < self.high:
+            return valeur
+        raise ValError(ufmt(_(tr(u"%s devrait etre comprise entre %s et %s")),
+                            valeur, self.low, self.high))
+
+    def verif_item(self, valeur):
+        return valeur > self.low and valeur < self.high
+
+    def info_erreur_item(self):
+        return ufmt(_(tr(u"La valeur doit etre comprise entre %s et %s")), self.low, self.high)
+
+    def verif_cata(self):
+        if self.low > self.high:
+            return 0
+        return 1
+
 
 class CardVal(Valid):
 
 class CardVal(Valid):
-      """
-          Exemple de classe validateur : verification qu'une liste est
-          d'une longueur superieur a un minimum (min) et inferieure
-          a un maximum (max).
-          Susceptible de remplacer les attributs "min" "max" dans les
-          catalogues
-      """
-      def __init__(self,min='**',max='**'):
-          self.min=min
-          self.max=max
-          self.cata_info="%s doit etre inferieur a %s" % (min,max)
-
-      def info(self):
-          return "longueur de liste comprise entre  %s et %s" % (self.min,self.max)
-
-      def info_erreur_liste(self):
-          return "Le cardinal de la liste doit etre compris 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 convert(self,valeur):
-          if type(valeur) in (types.ListType,types.TupleType):
-             l=len(valeur)
-          elif valeur is None:
-             l=0
-          else:
-             l=1
-          if self.max != '**' and l > self.max:raise ValError("%s devrait etre de longueur inferieure a %s" %(valeur,self.max))
-          if self.min != '**' and l < self.min:raise ValError("%s devrait etre de longueur superieure a %s" %(valeur,self.min))
-          return valeur
-
-      def verif_item(self,valeur):
-          return 1
-
-      def verif(self,valeur):
-          if type(valeur) in (types.ListType,types.TupleType):
-             if self.max != '**' and len(valeur) > self.max:return 0
-             if self.min != '**' and len(valeur) < self.min:return 0
-             return 1
-          else:
-             if self.max != '**' and 1 > self.max:return 0
-             if self.min != '**' and 1 < self.min:return 0
-             return 1
-
-      def verif_cata(self):
-          if self.min != '**' and self.max != '**' and self.min > self.max : return 0
-          return 1
-
-      def valide_liste_partielle(self,liste_courante=None):
-          validite=1
-          if liste_courante != None :
-             if len(liste_courante) > self.max :
-                validite=0
-          return validite
+
+    """
+        Exemple de classe validateur : verification qu'une liste est
+        d'une longueur superieur a un minimum (min) et inferieure
+        a un maximum (max).
+        Susceptible de remplacer les attributs "min" "max" dans les
+        catalogues
+    """
+
+    def __init__(self, min='**', max='**'):
+        self.min = min
+        self.max = max
+        self.cata_info = ufmt(_(tr(u"%s doit etre inferieur a %s")), min, max)
+
+    def info(self):
+        return ufmt(_(tr(u"longueur de liste comprise entre  %s et %s")), self.min, self.max)
+
+    def info_erreur_liste(self):
+        return ufmt(
+            _(tr(u"Le cardinal de la liste doit etre compris 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 convert(self, valeur):
+        if is_sequence(valeur):
+            l = len(valeur)
+        elif valeur is None:
+            l = 0
+        else:
+            l = 1
+        if self.max != '**' and l > self.max:
+            raise ValError(
+                ufmt(_(tr(u"%s devrait etre de longueur inferieure a %s")), valeur, self.max))
+        if self.min != '**' and l < self.min:
+            raise ValError(
+                ufmt(_(tr(u"%s devrait etre de longueur superieure a %s")), valeur, self.min))
+        return valeur
+
+    def verif_item(self, valeur):
+        return 1
+
+    def verif(self, valeur):
+        if is_sequence(valeur):
+            if self.max != '**' and len(valeur) > self.max:
+                return 0
+            if self.min != '**' and len(valeur) < self.min:
+                return 0
+            return 1
+        else:
+            if self.max != '**' and 1 > self.max:
+                return 0
+            if self.min != '**' and 1 < self.min:
+                return 0
+            return 1
+
+    def verif_cata(self):
+        if self.min != '**' and self.max != '**' and self.min > self.max:
+            return 0
+        return 1
+
+    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):
 
 class PairVal(ListVal):
-      """
-          Exemple de classe validateur : verification qu'une valeur
-          est paire.
-          Pour une liste on verifie que tous les elements sont
-          pairs
-      """
-      def __init__(self):
-          ListVal.__init__(self)
-          self.cata_info=""
-
-      def info(self):
-          return "valeur paire"
-
-      def info_erreur_item(self):
-          return "La valeur saisie doit etre paire"
-
-      def convert(self,valeur):
-          for val in valeur:
-             v=self.adapt(val)
-             if v % 2 != 0:raise ValError("%s contient des valeurs non paires" % repr(valeur))
-          return valeur
-
-      def default(self,valeur):
-          return valeur
-
-      def verif_item(self,valeur):
-          if type(valeur) not in (int,long):
-             return 0
-          return valeur % 2 == 0
-
-      def verif(self,valeur):
-          if type(valeur) in (types.ListType,types.TupleType):
-             for val in valeur:
-                if val % 2 != 0:return 0
-             return 1
-          else:
-             if valeur % 2 != 0:return 0
-             return 1
+
+    """
+        Exemple de classe validateur : verification qu'une valeur
+        est paire.
+        Pour une liste on verifie que tous les elements sont
+        pairs
+    """
+
+    def __init__(self):
+        ListVal.__init__(self)
+        self.cata_info = ""
+
+    def info(self):
+        return _(u"valeur paire")
+
+    def info_erreur_item(self):
+        return _(u"La valeur saisie doit etre paire")
+
+    def convert(self, valeur):
+        for val in valeur:
+            v = self.adapt(val)
+            if v % 2 != 0:
+                raise ValError(
+                    ufmt(_(tr(u"%s contient des valeurs non paires")), repr(valeur)))
+        return valeur
+
+    def default(self, valeur):
+        return valeur
+
+    def verif_item(self, valeur):
+        if type(valeur) not in (int, long):
+            return 0
+        return valeur % 2 == 0
+
+    def verif(self, valeur):
+        if is_sequence(valeur):
+            for val in valeur:
+                if val % 2 != 0:
+                    return 0
+            return 1
+        else:
+            if valeur % 2 != 0:
+                return 0
+            return 1
+
 
 class EnumVal(ListVal):
 
 class EnumVal(ListVal):
-      """
-          Exemple de classe validateur : verification qu'une valeur
-          est prise dans une liste de valeurs.
-          Susceptible de remplacer l attribut "into" dans les catalogues
-      """
-      def __init__(self,into=()):
-          if type(into) not in (types.ListType,types.TupleType): into=(into,)
-          self.into=into
-          self.cata_info=""
-
-      def info(self):
-          return "valeur dans %s" % `self.into`
-
-      def convert_item(self,valeur):
-          if valeur in self.into:return valeur
-          raise ValError("%s contient des valeurs hors des choix possibles: %s " %(valeur,self.into))
-
-      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:
-             liste_choix=[]
-             for e in into_courant:
-                 if e in self.into:
+
+    """
+        Exemple de classe validateur : verification qu'une valeur
+        est prise dans une liste de valeurs.
+        Susceptible de remplacer l attribut "into" dans les catalogues
+    """
+
+    def __init__(self, into=()):
+        if not is_sequence(into):
+            into = (into,)
+        self.into = into
+        self.cata_info = ""
+
+    def info(self):
+        return "valeur dans %s" % `self.into`
+
+    def convert_item(self, valeur):
+        if valeur in self.into:
+            return valeur
+        raise ValError(
+            ufmt(_(tr(u"%s contient des valeurs hors des choix possibles: %s ")),
+                 valeur, self.into))
+
+    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:
+            liste_choix = []
+            for e in into_courant:
+                if e in self.into:
                     liste_choix.append(e)
                     liste_choix.append(e)
-          return liste_choix
+        return liste_choix
+
+    def info_erreur_item(self):
+        return _(u"La valeur n'est pas dans la liste des choix possibles")
 
 
-      def info_erreur_item(self):
-          return "La valeur n'est pas dans la liste des choix possibles"
 
 def ImpairVal(valeur):
     """
 
 def ImpairVal(valeur):
     """
@@ -1083,133 +1385,335 @@ def ImpairVal(valeur):
         Cette fonction est un validateur. Elle verifie que la valeur passee
         est bien un nombre impair.
     """
         Cette fonction est un validateur. Elle verifie que la valeur passee
         est bien un nombre impair.
     """
-    if type(valeur) in (types.ListType,types.TupleType):
-       for val in valeur:
-           if val % 2 != 1:return 0
-       return 1
+    if is_sequence(valeur):
+        for val in valeur:
+            if val % 2 != 1:
+                return 0
+        return 1
     else:
     else:
-       if valeur % 2 != 1:return 0
-       return 1
+        if valeur % 2 != 1:
+            return 0
+        return 1
+
+ImpairVal.info = "valeur impaire"
 
 
-ImpairVal.info="valeur impaire"
 
 class F1Val(Valid):
 
 class F1Val(Valid):
-      """
-          Exemple de validateur
-          Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
-          que la somme des cles A et B vaut une valeur donnee
-          en parametre du validateur
-      """
-      def __init__(self,somme=10):
-          self.somme=somme
-          self.cata_info=""
-
-      def info(self):
-          return "valeur %s pour la somme des cles A et B " % self.somme
-
-      def verif(self,valeur):
-          if type(valeur) in (types.ListType,types.TupleType):
-             for val in valeur:
-                if not val.has_key("A"):return 0
-                if not val.has_key("B"):return 0
-                if val["A"]+val["B"]  != self.somme:return 0
-             return 1
-          else:
-             if not valeur.has_key("A"):return 0
-             if not valeur.has_key("B"):return 0
-             if valeur["A"]+valeur["B"]  != self.somme:return 0
-             return 1
+
+    """
+        Exemple de validateur
+        Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
+        que la somme des cles A et B vaut une valeur donnee
+        en parametre du validateur
+    """
+
+    def __init__(self, somme=10):
+        self.somme = somme
+        self.cata_info = ""
+
+    def info(self):
+        return ufmt(_(tr(u"valeur %s pour la somme des cles A et B ")), self.somme)
+
+    def verif(self, valeur):
+        if is_sequence(valeur):
+            for val in valeur:
+                if not val.has_key("A"):
+                    return 0
+                if not val.has_key("B"):
+                    return 0
+                if val["A"] + val["B"] != self.somme:
+                    return 0
+            return 1
+        else:
+            if not valeur.has_key("A"):
+                return 0
+            if not valeur.has_key("B"):
+                return 0
+            if valeur["A"] + valeur["B"] != self.somme:
+                return 0
+            return 1
+
 
 class FunctionVal(Valid):
 
 class FunctionVal(Valid):
-      """
-          Exemple de validateur
-          Cette classe est un validateur qui est initialise avec une fonction
-      """
-      def __init__(self,function):
-          self.function=function
 
 
-      def info(self):
-          return self.function.info
+    """
+        Exemple de validateur
+        Cette classe est un validateur qui est initialise avec une fonction
+    """
+
+    def __init__(self, function):
+        self.function = function
+
+    def info(self):
+        return self.function.info
+
+    def verif(self, valeur):
+        return self.function(valeur)
 
 
-      def verif(self,valeur):
-          return self.function(valeur)
+    def verif_item(self, valeur):
+        return self.function(valeur)
+
+    def convert(self, valeur):
+        return valeur
+
+# MC ca ne devrait plus servir !
+CoercableFuncs = {types.IntType:     int,
+                  types.LongType:    long,
+                  types.FloatType:   float,
+                  types.ComplexType: complex,
+                  types.UnicodeType: unicode}
 
 
-#MC ca ne devrait plus servir !
-CoercableFuncs = { types.IntType:     int,
-                   types.LongType:    long,
-                   types.FloatType:   float,
-                   types.ComplexType: complex,
-                   types.UnicodeType: unicode }
 
 class TypeVal(ListVal):
 
 class TypeVal(ListVal):
-      """
-          Exemple de validateur
-          Cette classe est un validateur qui controle qu'une valeur
-          est bien du type Python attendu.
-          Pour une liste on verifie que tous les elements sont du bon type.
-          Semblable a InstanceVal mais ici on fait le test par tentative de conversion
-          alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
-      """
-      def __init__(self, aType):
-          #Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
-          #type(1) == int;type(0.2)==float;etc.
-          if type(aType) != types.TypeType:
-             aType=type(aType)
-          self.aType=aType
-          try:
-             self.coerce=CoercableFuncs[ aType ]
-          except:
-             self.coerce = self.identity
-
-      def info(self):
-          return "valeur de %s" % self.aType
-
-      def identity ( self, value ):
-          if type( value ) == self.aType:
-             return value
-          raise ValError
-
-      def convert_item(self,valeur):
-          return   self.coerce(valeur)
-
-      def verif_item(self,valeur):
-          try:
-             self.coerce(valeur)
-          except:
-             return 0
-          return 1
+
+    """
+        Exemple de validateur
+        Cette classe est un validateur qui controle qu'une valeur
+        est bien du type Python attendu.
+        Pour une liste on verifie que tous les elements sont du bon type.
+        Semblable a InstanceVal mais ici on fait le test par tentative de conversion
+        alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
+    """
+
+    def __init__(self, aType):
+        # Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
+        # type(1) == int;type(0.2)==float;etc.
+        if type(aType) != types.TypeType:
+            aType = type(aType)
+        self.aType = aType
+        try:
+            self.coerce = CoercableFuncs[aType]
+        except:
+            self.coerce = self.identity
+
+    def info(self):
+        return ufmt(_(tr(u"valeur de %s")), self.aType)
+
+    def identity(self, value):
+        if type(value) == self.aType:
+            return value
+        raise ValError
+
+    def convert_item(self, valeur):
+        return self.coerce(valeur)
+
+    def verif_item(self, valeur):
+        try:
+            self.coerce(valeur)
+        except:
+            return 0
+        return 1
+
 
 class InstanceVal(ListVal):
 
 class InstanceVal(ListVal):
-      """
-          Exemple de validateur
-          Cette classe est un validateur qui controle qu'une valeur est
-          bien une instance (au sens Python) d'une classe
-          Pour une liste on verifie chaque element de la liste
-      """
-      def __init__(self,aClass):
-          #Si aClass est une classe on la memorise dans self.aClass
-          #sinon c'est une instance dont on memorise la classe
-          if type(aClass) == types.InstanceType:
-             #instance ancienne mode
-             aClass=aClass.__class__
-          elif type(aClass) == types.ClassType:
-             #classe ancienne mode
-             aClass=aClass
-          elif type(aClass) == type:
-             #classe nouvelle mode
-             aClass=aClass
-          elif isinstance(aClass,object):
-             #instance nouvelle mode
-             aClass=type(aClass)
-          else:
-             raise ValError("type non supporte")
-
-          self.aClass=aClass
-
-      def info(self):
-          return "valeur d'instance de %s" % self.aClass.__name__
-
-      def verif_item(self,valeur):
-          if not isinstance(valeur,self.aClass): return 0
-          return 1
 
 
+    """
+        Exemple de validateur
+        Cette classe est un validateur qui controle qu'une valeur est
+        bien une instance (au sens Python) d'une classe
+        Pour une liste on verifie chaque element de la liste
+    """
+
+    def __init__(self, aClass):
+        # Si aClass est une classe on la memorise dans self.aClass
+        # sinon c'est une instance dont on memorise la classe
+        if type(aClass) == types.InstanceType:
+            # instance ancienne mode
+            aClass = aClass.__class__
+        elif type(aClass) == types.ClassType:
+            # classe ancienne mode
+            aClass = aClass
+        elif type(aClass) == type:
+            # classe nouvelle mode
+            aClass = aClass
+        elif isinstance(aClass, object):
+            # instance nouvelle mode
+            aClass = type(aClass)
+        else:
+            raise ValError(_(u"type non supporté"))
+
+        self.aClass = aClass
+
+    def info(self):
+        return ufmt(_(tr(u"valeur d'instance de %s")), self.aClass.__name__)
+
+    def verif_item(self, valeur):
+        if not isinstance(valeur, self.aClass):
+            return 0
+        return 1
+
+
+class VerifTypeTuple(Valid, ListVal):
+
+    def __init__(self, typeDesTuples):
+        self.typeDesTuples = typeDesTuples
+        Valid.__init__(self)
+        self.cata_info = ""
+
+    def info(self):
+        return _(tr(": verifie les types dans un tuple"))
+
+    def info_erreur_liste(self):
+        return _(tr("Les types entres ne sont pas permis"))
+
+    def default(self, valeur):
+        # if valeur in self.liste : raise ValError("%s est un doublon" %
+        # valeur)
+        return valeur
+
+    def is_list(self):
+        return 1
+
+    def convert_item(self, valeur):
+        if len(valeur) != len(self.typeDesTuples):
+            raise ValError(
+                ufmt(_(tr(u"%s devrait etre de type  %s ")), valeur, self.typeDesTuples))
+        for i in range(len(valeur)):
+            ok = self.verifType(valeur[i], self.typeDesTuples[i])
+            if ok != 1:
+                raise ValError(
+                    ufmt(_(tr(u"%s devrait etre de type  %s ")), valeur, self.typeDesTuples))
+        return valeur
+
+    def verif_item(self, valeur):
+        try:
+            if len(valeur) != len(self.typeDesTuples):
+                return 0
+            for i in range(len(valeur)):
+                ok = self.verifType(valeur[i], self.typeDesTuples[i])
+                if ok != 1:
+                    return 0
+        except:
+            return 0
+        return 1
+
+    def verifType(self, valeur, type_permis):
+        if type_permis == 'R':
+            if type(valeur) in (types.IntType, types.FloatType, types.LongType):
+                return 1
+        elif type_permis == 'I':
+            if type(valeur) in (types.IntType, types.LongType):
+                return 1
+        elif type_permis == 'C':
+            if self.is_complexe(valeur):
+                return 1
+        elif type_permis == 'TXM':
+            if type(valeur) == types.StringType:
+                return 1
+        elif isinstance(valeur, type_permis):
+                return 1
+        return 0
+
+    def verif(self, valeur):
+        if type(valeur) in (types.ListType, types.TupleType):
+            liste = list(valeur)
+            for val in liste:
+                if self.verif_item(val) != 1:
+                    return 0
+            return 1
+
+
+class VerifExiste(ListVal):
+
+    """
+       fonctionne avec into
+       Met une liste à jour selon les mot clefs existant
+       exemple si into = ("A","B","C")
+       si au niveau N du JDC les objets "A" et "C" existe
+       alors la liste des into deviendra ( "A","C")
+
+       niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
+       niveauVerif est defini par rapport au Noeud :
+       exemple niveauVerif = 1 : on verifie les freres
+               niveauVerif = 2 : on verifie les oncles..
+    """
+
+    def __init__(self, niveauVerif):
+        ListVal.__init__(self)
+        self.niveauVerif = niveauVerif
+        self.MCSimp = None
+        self.listeDesFreres = ()
+        self.fonctions = ('verifie_liste', 'set_MCSimp')
+
+    def is_list(self):
+        return 1
+
+    def verifie_liste(self, liste):
+        self.set_MCSimp(self.MCSimp)
+        for item in liste:
+            if not(item in self.listeDesFreres):
+                return 0
+        return 1
+
+    def verif_item(self, valeur):
+        self.set_MCSimp(self.MCSimp)
+        if valeur in self.listeDesFreres:
+            return 1
+        return 0
+
+    def set_MCSimp(self, MCSimp):
+        self.MCSimp = MCSimp
+        k = self.niveauVerif
+        mc = MCSimp
+        while (k != 0):
+            parent = mc.parent
+            mc = parent
+            k = k - 1
+        # on met la liste à jour
+        parent.forceRecalcul = self.niveauVerif
+        self.listeDesFreres = parent.liste_mc_presents()
+
+    def convert_item(self, valeur):
+        if valeur in self.listeDesFreres:
+            return valeur
+        raise ValError(
+            ufmt(_(tr(u"%s n'est pas dans %s")), valeur, self.listeDesFreres))
+
+
+class RegExpVal(ListVal):
+
+    """
+    Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
+    """
+
+    errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
+
+    def __init__(self, pattern):
+        self.pattern = pattern
+        self.compiled_regexp = re.compile(pattern)
+
+    def info(self):
+        return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
+
+    def verif_item(self, valeur):
+        if self.compiled_regexp.match(valeur):
+            return 1
+        else:
+            return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
+
+    def convert_item(self, valeur):
+        if self.compiled_regexp.match(valeur):
+            return valeur
+        else:
+            raise ValError(self.errormsg %
+                           {"value": valeur, "pattern": self.pattern})
+
+
+class FileExtVal(RegExpVal):
+
+    """
+    Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
+    """
+
+    def __init__(self, ext):
+        self.ext = ext
+        self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {
+            "ext": ext}
+        #RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
+        #PNPN Modif pour Adao
+        #RegExpVal.__init__(self, "^[\S]+\.%s$" % self.ext
+        RegExpVal.__init__(self, "^\S+\.%s$" % self.ext)
+
+
+    def info(self):
+        return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext