From: eficas <> Date: Thu, 29 Jan 2004 18:24:03 +0000 (+0000) Subject: CCAR : Suppression des surcharges de methodes faites pour Eficas1.5 X-Git-Tag: CC_param_poursuite~283 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=ff6d6509dbf66da65b7c90fa6ffac508686f7e15;p=modules%2Feficas.git CCAR : Suppression des surcharges de methodes faites pour Eficas1.5 et réintégration dans Noyau et Validation --- diff --git a/Ihm/I_A_CLASSER.py b/Ihm/I_A_CLASSER.py index e1f19ca5..3848167b 100644 --- a/Ihm/I_A_CLASSER.py +++ b/Ihm/I_A_CLASSER.py @@ -37,15 +37,3 @@ class A_CLASSER(I_REGLE.REGLE): text = text + t[0:-4] +'\n' return text - def init_couples_permis(self): - """ - Crée la liste des couples permis parmi les self.args, - càd pour chaque élément de self.args0 crée tous les couples possibles - avec un élément de self.args1 - """ - liste = [] - for arg0 in self.args0: - for arg1 in self.args1: - liste.append((arg0,arg1)) - self.liste_couples = liste - diff --git a/Ihm/I_ETAPE.py b/Ihm/I_ETAPE.py index 6bcebd97..3b51fbb6 100644 --- a/Ihm/I_ETAPE.py +++ b/Ihm/I_ETAPE.py @@ -291,49 +291,6 @@ class ETAPE(I_MCCOMPO.MCCOMPO): for child in self.mc_liste : child.replace_concept(old_sd,sd) -#ATTENTION SURCHARGE: cette methode doit etre gardée en synchronisation avec Noyau - def make_register(self): - """ - Initialise les attributs jdc, id, niveau et réalise les - enregistrements nécessaires - Pour EFICAS, on tient compte des niveaux - Surcharge la methode make_register du package Noyau - """ - if self.parent : - self.jdc = self.parent.get_jdc_root() - self.id= self.parent.register(self) - if self.definition.niveau : - # La définition est dans un niveau. En plus on - # l'enregistre dans le niveau - self.nom_niveau_definition = self.definition.niveau.nom - self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition] - self.niveau.register(self) - else: - # La définition est au niveau global - self.nom_niveau_definition = 'JDC' - self.niveau=self.parent - else: - self.jdc = self.parent =None - self.id=None - self.niveau=None - - def copy(self): - """ Méthode qui retourne une copie de self non enregistrée auprès du JDC - et sans sd - """ - etape = copy(self) - etape.sd = None - etape.state = 'modified' - etape.reuse = None - etape.sdnom = None - etape.etape=etape - etape.mc_liste=[] - for objet in self.mc_liste: - new_obj = objet.copy() - new_obj.reparent(etape) - etape.mc_liste.append(new_obj) - return etape - def get_noms_sd_oper_reentrant(self): """ Retourne la liste des noms de concepts utilisés à l'intérieur de la commande @@ -354,16 +311,6 @@ class ETAPE(I_MCCOMPO.MCCOMPO): l_noms.sort() return l_noms - def get_sd_utilisees(self): - """ - Retourne la liste des concepts qui sont utilisés à l'intérieur d'une commande - ( comme valorisation d'un MCS) - """ - l=[] - for child in self.mc_liste: - l.extend(child.get_sd_utilisees()) - return l - def get_genealogie(self): """ Retourne la liste des noms des ascendants de l'objet self @@ -371,16 +318,6 @@ class ETAPE(I_MCCOMPO.MCCOMPO): """ return [self.nom] - def reparent(self,parent): - """ - Cette methode sert a reinitialiser la parente de l'objet - """ - self.parent=parent - self.jdc=parent.get_jdc_root() - self.etape=self - for mocle in self.mc_liste: - mocle.reparent(self) - def verif_existence_sd(self): """ Vérifie que les structures de données utilisées dans self existent bien dans le contexte @@ -412,91 +349,29 @@ class ETAPE(I_MCCOMPO.MCCOMPO): return self.sd - def Build_sd_old(self,nom): +#ATTENTION SURCHARGE: cette methode doit etre gardée en synchronisation avec Noyau + def make_register(self): """ - Construit le concept produit de l'opérateur. Deux cas - peuvent se présenter : - - - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création - et le nommage du concept. - - - le parent est défini. Dans ce cas, l'étape demande au parent la création et - le nommage du concept. - + Initialise les attributs jdc, id, niveau et réalise les + enregistrements nécessaires + Pour EFICAS, on tient compte des niveaux + Surcharge la methode make_register du package Noyau """ - if not self.isactif():return - # FR : attention cette méthode ne devrait pas se trouver là car elle surcharge celle qui - # se trouve dans N_ETAPE.py et elle est partie intégrante du noyau, mais, suite à l'absence de - # test de validité de l'opérateur avant d'essayer de déterminer la sd produite, on n'arrivait - # pas à relire avec EFICAS un fichier contenant une étape encore incomplète du style : - # sansnom = AFFE_CHAR_CINE(MODELE=None) - # Suite à la stabilisation du noyau d'Aster, je n'ai pas eu d'autre solution que de surcharger - # cette méthode ici en rajoutant le test manquant ... - # CCAR : cette modification ne corrige le probleme qu'en partie. Il faudrait probablement - # supprimer les erreurs fatales (exception ) et retourner systematiquement un objet produit - # meme en cas d'erreur et reporter l'emission du message d'erreur a la phase de validation - # - if not self.isvalid(sd='non') : return - self.sdnom=nom - try: - if self.parent: - sd= self.parent.create_sdprod(self,nom) - if type(self.definition.op_init) == types.FunctionType: - apply(self.definition.op_init,(self,self.parent.g_context)) + if self.parent : + self.jdc = self.parent.get_jdc_root() + self.id= self.parent.register(self) + if self.definition.niveau : + # La définition est dans un niveau. En plus on + # l'enregistre dans le niveau + self.nom_niveau_definition = self.definition.niveau.nom + self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition] + self.niveau.register(self) else: - sd=self.get_sd_prod() - # On n'utilise pas self.definition.op_init car self.parent - # n'existe pas - if sd != None and self.reuse == None: - # On ne nomme le concept que dans le cas de non reutilisation - # d un concept - sd.nom=nom - if self.jdc and self.jdc.par_lot == "NON" : - self.Execute() - return sd - except AsException,e: - # Une erreur s'est produite lors de la construction du concept - # Comme on est dans EFICAS, on essaie de poursuivre quand meme - # Si on poursuit, on a le choix entre deux possibilités : - # 1. on annule la sd associée à self - # 2. on la conserve mais il faut la retourner - # En plus il faut rendre coherents sdnom et sd.nom - self.sd=None - self.sdnom=None - self.state="unchanged" - self.valid=0 - return self.sd + # La définition est au niveau global + self.nom_niveau_definition = 'JDC' + self.niveau=self.parent + else: + self.jdc = self.parent =None + self.id=None + self.niveau=None - #raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], - # 'fichier : ',self.appel[1],e) - except EOFError: - # XXX Normalement le contexte courant doit etre le parent. - # Il n'y a pas de raison de remettre le contexte au parent - #self.reset_current_step() - raise - except : - l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) - raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], - 'fichier : ',self.appel[1]+'\n', - string.join(l)) - - - - - - - - - - - - - - - - - - - - - diff --git a/Ihm/I_FONCTION.py b/Ihm/I_FONCTION.py index 1d9fc272..4a4676dd 100644 --- a/Ihm/I_FONCTION.py +++ b/Ihm/I_FONCTION.py @@ -21,7 +21,6 @@ from I_ASSD import ASSD class FONCTION(ASSD): def __init__(self,etape=None,sd=None,reg='oui'): - #ASSD.__init__(self,etape=etape,sd=sd,reg=reg) if reg=='oui': self.jdc.register_fonction(self) diff --git a/Ihm/I_JDC.py b/Ihm/I_JDC.py index 8768ec59..85b15224 100644 --- a/Ihm/I_JDC.py +++ b/Ihm/I_JDC.py @@ -43,14 +43,6 @@ class JDC(I_OBJECT.OBJECT): self.recorded_units={} self.old_recorded_units={} - def get_cmd(self,nomcmd): - """ - Retourne l'objet de type COMMANDE de nom nomcmd - """ - for cata in self.cata: - if hasattr(cata,nomcmd): - return getattr(cata,nomcmd) - def get_sd_avant_du_bon_type(self,etape,types_permis): """ Retourne la liste des concepts avant etape d'un type acceptable @@ -249,43 +241,6 @@ class JDC(I_OBJECT.OBJECT): if sd:return sd return self.get_sd_apres_etape(nom_sd,etape,avec) - def get_contexte_avant(self,etape): - """ - Retourne le dictionnaire des concepts connus avant etape - On tient compte des commandes qui modifient le contexte - comme DETRUIRE ou les macros - Si etape == None, on retourne le contexte en fin de JDC - """ - # L'étape courante pour laquelle le contexte a été calculé est - # mémorisée dans self.index_etape_courante - # XXX on pourrait faire mieux dans le cas PAR_LOT="NON" : en - # mémorisant l'étape - # courante pendant le processus de construction des étapes. - # Si on insère des commandes (par ex, dans EFICAS), il faut préalablement - # remettre ce pointeur à 0 - if etape: - index_etape=self.etapes.index(etape) - else: - index_etape=len(self.etapes) - if index_etape >= self.index_etape_courante: - # On calcule le contexte en partant du contexte existant - d=self.current_context - if self.index_etape_courante==0 and self.context_ini: - d.update(self.context_ini) - liste_etapes=self.etapes[self.index_etape_courante:index_etape] - else: - d=self.current_context={} - if self.context_ini:d.update(self.context_ini) - liste_etapes=self.etapes - - for e in liste_etapes: - if e is etape: - break - if e.isactif(): - e.update_context(d) - self.index_etape_courante=index_etape - return d - def get_contexte_apres(self,etape): """ Retourne le dictionnaire des concepts connus apres etape @@ -355,29 +310,6 @@ class JDC(I_OBJECT.OBJECT): self.exec_compile() self.active_etapes() - def register(self,etape): - """ - Cette méthode ajoute etape dans la liste - des etapes self.etapes et retourne l identificateur d'étape - fourni par l appel a g_register - - A quoi sert editmode ? - - Si editmode vaut 1, on est en mode edition de JDC. On cherche - à enregistrer une étape que l'on a créée avec eficas (en passant - par addentite) auquel cas on ne veut récupérer que son numéro - d'enregistrement et c'est addentité qui l'enregistre dans - self.etapes à la bonne place... - - Si editmode vaut 0, on est en mode relecture d'un fichier de - commandes et on doit enregistrer l'étape à la fin de self.etapes - (dans ce cas l'ordre des étapes est bien l'ordre chronologique - de leur création ) - """ - if not self.editmode: - self.etapes.append(etape) - else: - pass - return self.g_register(etape) - def register_parametre(self,param): """ Cette méthode sert à ajouter un paramètre dans la liste des paramètres @@ -469,33 +401,6 @@ class JDC(I_OBJECT.OBJECT): if l : l_mc.extend(l) return l_mc - def get_file(self,unite=None,fic_origine=''): - """ - Retourne le nom du fichier correspondant à un numero d'unité - logique (entier) ainsi que le source contenu dans le fichier - """ - if self.appli : - # Si le JDC est relié à une application maitre, on délègue la recherche - file,text = self.appli.get_file(unite,fic_origine) - else: - file = None - if unite != None: - if os.path.exists("fort."+str(unite)): - file= "fort."+str(unite) - if file == None : - raise AsException("Impossible de trouver le fichier correspondant \ - a l unite %s" % unite) - if not os.path.exists(file): - raise AsException("%s n'est pas un fichier existant" % unite) - fproc=open(file,'r') - text=fproc.read() - fproc.close() - if file == None : return None,None - text=string.replace(text,'\r\n','\n') - linecache.cache[file]=0,0,string.split(text,'\n'),file - return file,text - - def get_genealogie(self): """ Retourne la liste des noms des ascendants de l'objet self @@ -503,41 +408,6 @@ class JDC(I_OBJECT.OBJECT): """ return [] - def NommerSdprod(self,sd,sdnom,restrict='non'): - """ - Nomme la SD apres avoir verifie que le nommage est possible : - nom non utilise - Si le nom est deja utilise, leve une exception - Met le concept créé dans le concept global g_context - """ - # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment - # Le dictionnaire g_context ne représente pas le contexte - # effectif avant une étape. - # Il faut utiliser get_contexte_avant avec indication de l'étape - # traitée. - # Cette etape est indiquee par l'attribut _etape_context qui a ete - # positionné préalablement par un appel à set_etape_context - - if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom - - if self._etape_context: - o=self.get_contexte_avant(self._etape_context).get(sdnom,None) - else: - o=self.sds_dict.get(sdnom,None) - - if isinstance(o,ASSD): - raise AsException("Nom de concept deja defini : %s" % sdnom) - - # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja. - # Ajoute a la creation (appel de reg_sd). - self.sds_dict[sdnom]=sd - sd.nom=sdnom - - # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC - if restrict == 'non': - self.g_context[sdnom]=sd - - def set_etape_context(self,etape): """ Positionne l'etape qui sera utilisee dans NommerSdProd pour @@ -610,17 +480,6 @@ class JDC(I_OBJECT.OBJECT): if fonction not in self.fonctions : self.fonctions.append(fonction) self.g_context[fonction.nom]=fonction - def delete_concept_after_etape(self,etape,sd): - """ - Met à jour les étapes du JDC qui sont après etape en fonction - de la disparition du concept sd - """ - index = self.etapes.index(etape)+1 - if index == len(self.etapes) : - return # etape est la dernière étape du jdc ...on ne fait rien ! - for child in self.etapes[index:]: - child.delete_concept(sd) - def delete_concept(self,sd): """ Inputs : @@ -663,4 +522,76 @@ class JDC(I_OBJECT.OBJECT): else: self.recorded_units[unit]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units) -#ATTENTION SURCHARGE : cette methode surcharge la methode du package Validation : a reintegrer +#ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau + def register(self,etape): + """ + Cette méthode ajoute etape dans la liste + des etapes self.etapes et retourne l identificateur d'étape + fourni par l appel a g_register + + A quoi sert editmode ? + - Si editmode vaut 1, on est en mode edition de JDC. On cherche + à enregistrer une étape que l'on a créée avec eficas (en passant + par addentite) auquel cas on ne veut récupérer que son numéro + d'enregistrement et c'est addentité qui l'enregistre dans + self.etapes à la bonne place... + - Si editmode vaut 0, on est en mode relecture d'un fichier de + commandes et on doit enregistrer l'étape à la fin de self.etapes + (dans ce cas l'ordre des étapes est bien l'ordre chronologique + de leur création ) + """ + if not self.editmode: + self.etapes.append(etape) + else: + pass + return self.g_register(etape) + +#ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau + def NommerSdprod(self,sd,sdnom,restrict='non'): + """ + Nomme la SD apres avoir verifie que le nommage est possible : + nom non utilise + Si le nom est deja utilise, leve une exception + Met le concept créé dans le concept global g_context + """ + # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment + # Le dictionnaire g_context ne représente pas le contexte + # effectif avant une étape. + # Il faut utiliser get_contexte_avant avec indication de l'étape + # traitée. + # Cette etape est indiquee par l'attribut _etape_context qui a ete + # positionné préalablement par un appel à set_etape_context + + if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom + + if self._etape_context: + o=self.get_contexte_avant(self._etape_context).get(sdnom,None) + else: + o=self.sds_dict.get(sdnom,None) + + if isinstance(o,ASSD): + raise AsException("Nom de concept deja defini : %s" % sdnom) + + # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja. + # Ajoute a la creation (appel de reg_sd). + self.sds_dict[sdnom]=sd + sd.nom=sdnom + + # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC + if restrict == 'non': + self.g_context[sdnom]=sd + +#ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau + def delete_concept_after_etape(self,etape,sd): + """ + Met à jour les étapes du JDC qui sont après etape en fonction + de la disparition du concept sd + """ + index = self.etapes.index(etape)+1 + if index == len(self.etapes) : + return # etape est la dernière étape du jdc ...on ne fait rien ! + for child in self.etapes[index:]: + child.delete_concept(sd) + +#ATTENTION SURCHARGE : les methodes ci-dessous surchargent des methodes de Noyau et Validation : a reintegrer + diff --git a/Ihm/I_JDC_CATA.py b/Ihm/I_JDC_CATA.py index 9057c9b8..f5627571 100644 --- a/Ihm/I_JDC_CATA.py +++ b/Ihm/I_JDC_CATA.py @@ -23,6 +23,10 @@ class JDC_CATA: def __init__(self): self.l_noms_entites=[] + def get_liste_cmd(self): + self.l_noms_entites.sort() + return self.l_noms_entites + #ATTENTION SURCHARGE: cette methode doit etre synchronisée avec celle du Noyau def enregistre(self,commande): """ @@ -31,8 +35,3 @@ class JDC_CATA: """ N_JDC_CATA.JDC_CATA.enregistre(self,commande) self.l_noms_entites.append(commande.nom) - - def get_liste_cmd(self): - self.l_noms_entites.sort() - return self.l_noms_entites - diff --git a/Ihm/I_MACRO_ETAPE.py b/Ihm/I_MACRO_ETAPE.py index b87125c9..41e963a7 100644 --- a/Ihm/I_MACRO_ETAPE.py +++ b/Ihm/I_MACRO_ETAPE.py @@ -39,17 +39,6 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): self.typret=None self.recorded_units={} - def copy(self): - """ Méthode qui retourne une copie de self non enregistrée auprès du JDC - et sans sd - On surcharge la methode de ETAPE pour exprimer que les concepts crees - par la MACRO d'origine ne sont pas crees par la copie mais eventuellement - seulement utilises - """ - etape=I_ETAPE.ETAPE.copy(self) - etape.sdprods=[] - return etape - def get_sdprods(self,nom_sd): """ Fonction : retourne le concept produit par l etape de nom nom_sd @@ -268,94 +257,6 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): # On met g_context à blanc self.g_context={} -#ATTENTION SURCHARGE: a garder en synchro ou a reintegrer dans le Noyau - def Build_sd(self,nom): - """ - Methode de Noyau surchargee pour poursuivre malgre tout - si une erreur se produit pendant la creation du concept produit - """ - try: - sd=Noyau.N_MACRO_ETAPE.MACRO_ETAPE.Build_sd(self,nom) - self.state="modified" - except AsException,e: - # Une erreur s'est produite lors de la construction du concept - # Comme on est dans EFICAS, on essaie de poursuivre quand meme - # Si on poursuit, on a le choix entre deux possibilités : - # 1. on annule la sd associée à self - # 2. on la conserve mais il faut la retourner - # On choisit de l'annuler - # En plus il faut rendre coherents sdnom et sd.nom - self.sd=None - self.sdnom=None - self.state="unchanged" - self.valid=0 - - return self.sd - -#ATTENTION : cette methode surcharge celle de Noyau (a garder en synchro ou a reintegrer) - def Build_sd_old(self,nom): - """ - Construit le concept produit de l'opérateur. Deux cas - peuvent se présenter : - - - le parent n'est pas défini. Dans ce cas, l'étape prend en charge - la création et le nommage du concept. - - - le parent est défini. Dans ce cas, l'étape demande au parent la - création et le nommage du concept. - - """ - if not self.isactif():return - # CCAR : meme modification que dans I_ETAPE - if not self.isvalid(sd='non') : return - self.sdnom=nom - try: - # On positionne la macro self en tant que current_step pour que les - # étapes créées lors de l'appel à sd_prod et à op_init aient la macro - # comme parent - self.set_current_step() - if self.parent: - sd= self.parent.create_sdprod(self,nom) - if type(self.definition.op_init) == types.FunctionType: - apply(self.definition.op_init,(self,self.parent.g_context)) - else: - sd=self.get_sd_prod() - if sd != None and self.reuse == None: - # On ne nomme le concept que dans le cas de non reutilisation - # d un concept - sd.nom=nom - self.reset_current_step() - # Si on est arrive ici, l'etape est valide - self.state="unchanged" - self.valid=1 - if self.jdc and self.jdc.par_lot == "NON" : - self.Execute() - return sd - except AsException,e: - self.reset_current_step() - # Une erreur s'est produite lors de la construction du concept - # Comme on est dans EFICAS, on essaie de poursuivre quand meme - # Si on poursuit, on a le choix entre deux possibilités : - # 1. on annule la sd associée à self - # 2. on la conserve mais il faut qu'elle soit correcte et la retourner - # En plus il faut rendre coherents sdnom et sd.nom - # On choisit de retourner None et de mettre l'etape invalide - self.sd=None - self.sdnom=None - self.state="unchanged" - self.valid=0 - return self.sd - #raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], - # 'fichier : ',self.appel[1],e) - except EOFError: - raise - except : - self.reset_current_step() - l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) - raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], - 'fichier : ',self.appel[1]+'\n', - string.join(l)) - def make_contexte_include(self,fichier,text): """ Cette méthode sert à créer un contexte en interprétant un texte source @@ -461,79 +362,39 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): if hasattr(self,'fichier_unite') : self.parent.record_unit(self.fichier_unite,self) - def make_poursuite(self): - """ Cette methode est appelée par la fonction sd_prod de la macro POURSUITE - """ - if not hasattr(self,'fichier_ini') : - # Si le fichier n'est pas defini on le demande - f,text=self.get_file_memo(fic_origine=self.parent.nom) - # On memorise le fichier retourne - self.fichier_ini = f - self.fichier_unite = None - self.fichier_text = text - self.fichier_err=None - import Extensions.jdc_include - self.JdC_aux=Extensions.jdc_include.JdC_poursuite - self.contexte_fichier_init={} - - if f is None: - self.fichier_err="Le fichier POURSUITE n'est pas defini" - self.parent.record_unit(None,self) - raise Exception(self.fichier_err) - - try: - self.make_contexte_include(self.fichier_ini,self.fichier_text) - self.parent.record_unit(None,self) - except: - l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1]) - if self.jdc.appli: - self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier poursuite", - message="Ce fichier ne sera pas pris en compte\n"+string.join(l) - ) - self.parent.record_unit(None,self) - self.g_context={} - self.fichier_err = string.join(l) - self.contexte_fichier_init={} - raise - - else: - # Si le fichier est deja defini on ne reevalue pas le fichier - # et on leve une exception si une erreur a été enregistrée - self.update_fichier_init(None) - if self.fichier_err is not None: raise Exception(self.fichier_err) - - def get_file(self,unite=None,fic_origine=''): + def get_file_memo(self,unite=None,fic_origine=''): """Retourne le nom du fichier et le source correspondant a l'unite unite Initialise en plus recorded_units """ units={} - if self.jdc : + if self.parent.old_recorded_units.has_key(unite): + f,text,units=self.parent.old_recorded_units[unite] + self.recorded_units=units + return f,text + elif self.jdc : f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine) else: f,text=None,None self.recorded_units=units + if f is None and self.jdc.appli: + self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus", + message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini") return f,text - def get_file_memo(self,unite=None,fic_origine=''): +#ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro) + def get_file(self,unite=None,fic_origine=''): """Retourne le nom du fichier et le source correspondant a l'unite unite Initialise en plus recorded_units """ units={} - if self.parent.old_recorded_units.has_key(unite): - f,text,units=self.parent.old_recorded_units[unite] - self.recorded_units=units - return f,text - elif self.jdc : + if self.jdc : f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine) else: f,text=None,None self.recorded_units=units - if f is None and self.jdc.appli: - self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus", - message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini") return f,text -#ATTENTION : cette methode surcharge celle de Noyau (a garder en synchro) +#ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro) def make_include(self,unite=None): """ Inclut un fichier dont l'unite logique est unite @@ -589,7 +450,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): if self.fichier_err is not None: raise Exception(self.fichier_err) -#ATTENTION : cette methode surcharge celle de Noyau (a garder en synchro) +#ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro) def make_contexte(self,fichier,text): """ Cette méthode sert à créer un contexte pour INCLUDE_MATERIAU @@ -618,7 +479,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): self.contexte_fichier_init={} raise -#ATTENTION : cette methode surcharge celle de Noyau (a garder en synchro) +#ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro) def update_sdprod(self,cr='non'): # Cette methode peut etre appelee dans EFICAS avec des mots cles de # la commande modifies. Ceci peut conduire a la construction ou @@ -630,3 +491,69 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): CONTEXT.unset_current_step() return valid +#ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro + def Build_sd(self,nom): + """ + Methode de Noyau surchargee pour poursuivre malgre tout + si une erreur se produit pendant la creation du concept produit + """ + try: + sd=Noyau.N_MACRO_ETAPE.MACRO_ETAPE.Build_sd(self,nom) + self.state="modified" + except AsException,e: + # Une erreur s'est produite lors de la construction du concept + # Comme on est dans EFICAS, on essaie de poursuivre quand meme + # Si on poursuit, on a le choix entre deux possibilités : + # 1. on annule la sd associée à self + # 2. on la conserve mais il faut la retourner + # On choisit de l'annuler + # En plus il faut rendre coherents sdnom et sd.nom + self.sd=None + self.sdnom=None + self.state="unchanged" + self.valid=0 + + return self.sd + +#ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro + def make_poursuite(self): + """ Cette methode est appelée par la fonction sd_prod de la macro POURSUITE + """ + if not hasattr(self,'fichier_ini') : + # Si le fichier n'est pas defini on le demande + f,text=self.get_file_memo(fic_origine=self.parent.nom) + # On memorise le fichier retourne + self.fichier_ini = f + self.fichier_unite = None + self.fichier_text = text + self.fichier_err=None + import Extensions.jdc_include + self.JdC_aux=Extensions.jdc_include.JdC_poursuite + self.contexte_fichier_init={} + + if f is None: + self.fichier_err="Le fichier POURSUITE n'est pas defini" + self.parent.record_unit(None,self) + raise Exception(self.fichier_err) + + try: + self.make_contexte_include(self.fichier_ini,self.fichier_text) + self.parent.record_unit(None,self) + except: + l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1]) + if self.jdc.appli: + self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier poursuite", + message="Ce fichier ne sera pas pris en compte\n"+string.join(l) + ) + self.parent.record_unit(None,self) + self.g_context={} + self.fichier_err = string.join(l) + self.contexte_fichier_init={} + raise + + else: + # Si le fichier est deja defini on ne reevalue pas le fichier + # et on leve une exception si une erreur a été enregistrée + self.update_fichier_init(None) + if self.fichier_err is not None: raise Exception(self.fichier_err) + diff --git a/Ihm/I_MCBLOC.py b/Ihm/I_MCBLOC.py index 7b548225..c7829d2a 100644 --- a/Ihm/I_MCBLOC.py +++ b/Ihm/I_MCBLOC.py @@ -18,7 +18,5 @@ # # ====================================================================== import I_MCCOMPO -class MCBLOC(I_MCCOMPO.MCCOMPO): - def makeobjet(self): - return self.definition(val = None, nom = self.nom,parent = self.parent) +class MCBLOC(I_MCCOMPO.MCCOMPO):pass diff --git a/Ihm/I_MCCOMPO.py b/Ihm/I_MCCOMPO.py index 4731b55e..531c7703 100644 --- a/Ihm/I_MCCOMPO.py +++ b/Ihm/I_MCCOMPO.py @@ -184,7 +184,7 @@ class MCCOMPO(I_OBJECT.OBJECT): return 0 def isoblig(self): - return self.definition.statut=='o' + return 0 def addentite(self,name,pos=None): """ @@ -337,34 +337,6 @@ class MCCOMPO(I_OBJECT.OBJECT): nom = mc.nom del self.jdc.mc_globaux[nom] - def copy(self): - """ Retourne une copie de self """ - objet = self.makeobjet() - # FR : attention !!! avec makeobjet, objet a le même parent que self - # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!! - # FR : peut-on passer par là autrement que dans le cas d'une copie ??? - # FR --> je suppose que non - # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet - # Il me semble preferable de changer le parent a la fin quand la copie est acceptee - objet.valeur = copy(self.valeur) - objet.val = copy(self.val) - objet.mc_liste=[] - for obj in self.mc_liste: - new_obj = obj.copy() - new_obj.reparent(objet) - objet.mc_liste.append(new_obj) - return objet - - def get_sd_utilisees(self): - """ - Retourne la liste des concepts qui sont utilisés à l'intérieur de self - ( comme valorisation d'un MCS) - """ - l=[] - for child in self.mc_liste: - l.extend(child.get_sd_utilisees()) - return l - def get_liste_mc_inconnus(self): """ Retourne la liste des mots-clés inconnus dans self @@ -392,7 +364,7 @@ class MCCOMPO(I_OBJECT.OBJECT): """ liste_ajouts = [] liste_retraits = [] - dict = self.cree_dict_valeurs(self.mc_liste) + dict = self.cree_dict_condition(self.mc_liste) for k,v in self.definition.entites.items(): if v.label=='BLOC' : globs= self.jdc and self.jdc.condition_context or {} @@ -408,16 +380,6 @@ class MCCOMPO(I_OBJECT.OBJECT): liste_retraits.append(k) return liste_ajouts,liste_retraits - def reparent(self,parent): - """ - Cette methode sert a reinitialiser la parente de l'objet - """ - self.parent=parent - self.jdc=parent.get_jdc_root() - self.etape=parent.etape - for mocle in self.mc_liste: - mocle.reparent(self) - def verif_existence_sd(self): """ Vérifie que les structures de données utilisées dans self existent bien dans le contexte diff --git a/Ihm/I_MCFACT.py b/Ihm/I_MCFACT.py index 39670364..e78fc661 100644 --- a/Ihm/I_MCFACT.py +++ b/Ihm/I_MCFACT.py @@ -31,6 +31,6 @@ class MCFACT(I_MCCOMPO.MCCOMPO): else : return 0 - def makeobjet(self): - return self.definition(val = None, nom = self.nom,parent = self.parent) + def isoblig(self): + return self.definition.statut=='o' diff --git a/Ihm/I_MCLIST.py b/Ihm/I_MCLIST.py index 428abd31..9bde6f8b 100644 --- a/Ihm/I_MCLIST.py +++ b/Ihm/I_MCLIST.py @@ -51,9 +51,6 @@ class MCList: Une MCList n'est jamais obligatoire (même si le MCFACT qu'elle représente l'est """ return 0 - #for i in self.data: - # if i.isoblig():return 1 - #return 0 def liste_mc_presents(self): return [] @@ -81,21 +78,6 @@ class MCList: for child in self.data : child.replace_concept(old_sd,sd) - def copy(self): - """ - Réalise la copie d'une MCList - """ - liste = self.data[0].definition.list_instance() - # FR -->Il faut spécifier un parent pour la méthode init qui attend 2 arguments ... - liste.init(self.nom,self.parent) - for objet in self: - new_obj = objet.copy() - # Pour etre coherent avec le constructeur de mots cles facteurs N_FACT.__call__ - # dans lequel le parent de l'element d'une MCList est le parent de la MCList - new_obj.reparent(self.parent) - liste.append(new_obj) - return liste - def get_docu(self): return self.data[0].definition.get_docu() @@ -141,16 +123,6 @@ class MCList: if self.parent: self.parent.init_modif() - def get_etape(self): - """ - Retourne l'étape à laquelle appartient self - Un objet de la catégorie etape doit retourner self pour indiquer que - l'étape a été trouvée - XXX double emploi avec self.etape ??? - """ - if self.parent == None: return None - return self.parent.get_etape() - def get_genealogie(self): """ Retourne la liste des noms des ascendants. @@ -173,16 +145,6 @@ class MCList: dico=objet_cata.entites return objet_cata.ordre_mc - def reparent(self,parent): - """ - Cette methode sert a reinitialiser la parente de l'objet - """ - self.parent=parent - self.jdc=parent.jdc - self.etape=parent.etape - for mcfact in self.data: - mcfact.reparent(parent) - def verif_existence_sd(self): """ Vérifie que les structures de données utilisées dans self existent bien dans le contexte @@ -191,16 +153,6 @@ class MCList: for motcle in self.data : motcle.verif_existence_sd() - def get_sd_utilisees(self): - """ - Retourne la liste des concepts qui sont utilisés à l'intérieur de self - ( comme valorisation d'un MCS) - """ - l=[] - for motcle in self.data: - l.extend(motcle.get_sd_utilisees()) - return l - def get_fr(self): """ Retourne la chaine d'aide contenue dans le catalogue diff --git a/Ihm/I_MCSIMP.py b/Ihm/I_MCSIMP.py index e0a69f37..2ba38ccb 100644 --- a/Ihm/I_MCSIMP.py +++ b/Ihm/I_MCSIMP.py @@ -79,7 +79,7 @@ class MCSIMP(I_OBJECT.OBJECT): elif isinstance(self.valeur,ASSD): # Cas des ASSD txt=self.getval() - elif type(self.valeur) == types.InstanceType and val.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'): + elif type(self.valeur) == types.InstanceType and self.valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'): # Cas des PARAMETRES txt=str(self.valeur) else: @@ -181,50 +181,6 @@ class MCSIMP(I_OBJECT.OBJECT): def isoblig(self): return self.definition.statut=='o' -# def set_valeur(self,new_valeur,evaluation='oui'): -# """ -# Remplace la valeur de self(si elle existe) par new_valeur -# - si evaluation = 'oui' : -# essaie d'évaluer new_valeur dans le contexte -# - si evaluation = 'non' : -# n'essaie pas d'évaluer (on stocke une string ou -# une valeur de la liste into ) -# """ -# if evaluation == 'oui' and not self.wait_assd_or_geom(): -# valeur,test = self.eval_valeur(new_valeur) -# if test : -# self.val = new_valeur -# self.valeur = valeur -# self.init_modif() -# self.fin_modif() -# return 1 -# else: -# # On n'a pas trouve de concept ni réussi à évaluer la valeur -# # dans le contexte -# # Si le mot cle simple attend un type CO on crée un objet de ce -# # type de nom new_valeur -# if self.wait_co(): -# try: -# # Pour avoir la classe CO avec tous ses comportements -# from Accas import CO -# self.valeur=CO(new_valeur) -# except: -# traceback.print_exc() -# return 0 -# self.init_modif() -# self.val=self.valeur -# self.fin_modif() -# return 1 -# elif type(new_valeur)==types.StringType and self.wait_TXM(): -# self.init_modif() -# self.val = new_valeur -# self.valeur = new_valeur -# self.fin_modif() -# return 1 -# else: -# return 0 -# else : - # on ne fait aucune vérification ... def set_valeur(self,new_valeur,evaluation='oui'): self.init_modif() self.valeur = new_valeur @@ -301,33 +257,6 @@ class MCSIMP(I_OBJECT.OBJECT): self.val=sd self.init_modif() - def copy(self): - """ Retourne une copie de self """ - objet = self.makeobjet() - # il faut copier les listes et les tuples mais pas les autres valeurs - # possibles (réel,SD,...) - if type(self.valeur) in (types.ListType,types.TupleType): - objet.valeur = copy(self.valeur) - else: - objet.valeur = self.valeur - objet.val = objet.valeur - return objet - - def makeobjet(self): - return self.definition(val = None, nom = self.nom,parent = self.parent) - - def get_sd_utilisees(self): - """ - Retourne une liste qui contient la SD utilisée par self si c'est le cas - ou alors une liste vide - """ - l=[] - if type(self.valeur) == types.InstanceType: - #XXX Est ce différent de isinstance(self.valeur,ASSD) ?? - if issubclass(self.valeur.__class__,ASSD) : l.append(self.valeur) - return l - - def set_valeur_co(self,nom_co): """ Affecte à self l'objet de type CO et de nom nom_co @@ -368,14 +297,6 @@ class MCSIMP(I_OBJECT.OBJECT): self.etape.get_type_produit(force=1) return 1,"Concept créé" - def reparent(self,parent): - """ - Cette methode sert a reinitialiser la parente de l'objet - """ - self.parent=parent - self.jdc=parent.jdc - self.etape=parent.etape - def verif_existence_sd(self): """ Vérifie que les structures de données utilisées dans self existent bien dans le contexte @@ -418,184 +339,3 @@ class MCSIMP(I_OBJECT.OBJECT): #ATTENTION SURCHARGE : toutes les methodes ci apres sont des surcharges du Noyau et de Validation # Elles doivent etre reintegrees des que possible - def is_complexe(self,valeur): - """ Retourne 1 si valeur est un complexe, 0 sinon """ - if type(valeur) == types.InstanceType : - #XXX je n'y touche pas pour ne pas tout casser mais il serait - #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple - if valeur.__class__.__name__ in ('EVAL','complexe','PARAMETRE_EVAL'): - return 1 - elif valeur.__class__.__name__ in ('PARAMETRE',): - # il faut tester si la valeur du parametre est un entier - #XXX ne serait ce pas plutot complexe ???? sinon expliquer - return self.is_complexe(valeur.valeur) - else: - print "Objet non reconnu dans is_complexe %s" %`valeur` - return 0 - # Pour permettre l'utilisation de complexes Python - #elif type(valeur) == types.ComplexType: - #return 1 - elif type(valeur) == types.ListType : - # On n'autorise pas les listes de complexes - return 0 - elif type(valeur) != types.TupleType : - # Un complexe doit etre un tuple - return 0 - else: - if len(valeur) != 3 : - return 0 - else: - if type(valeur[0]) != types.StringType : return 0 - if string.strip(valeur[0]) not in ('RI','MP'): - return 0 - else: - if not self.is_reel(valeur[1]) or not self.is_reel(valeur[2]) : return 0 - else: return 1 - - def is_reel(self,valeur): - """ - Retourne 1 si valeur est un reel, 0 sinon - """ - if type(valeur) == types.InstanceType : - #XXX je n'y touche pas pour ne pas tout casser mais il serait - #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple - #XXX ou valeur.is_reel() - #XXX ou encore valeur.compare(self.is_reel) - if valeur.__class__.__name__ in ('EVAL','reel','PARAMETRE_EVAL') : - return 1 - elif valeur.__class__.__name__ in ('PARAMETRE',): - # il faut tester si la valeur du parametre est un réel - return self.is_reel(valeur.valeur) - else: - print "Objet non reconnu dans is_reel %s" %`valeur` - return 0 - elif type(valeur) not in (types.IntType,types.FloatType,types.LongType): - # ce n'est pas un réel - return 0 - else: - return 1 - - def is_entier(self,valeur): - """ Retourne 1 si valeur est un entier, 0 sinon """ - if type(valeur) == types.InstanceType : - #XXX je n'y touche pas pour ne pas tout casser mais il serait - #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple - if valeur.__class__.__name__ in ('EVAL','entier','PARAMETRE_EVAL') : - return 1 - elif valeur.__class__.__name__ in ('PARAMETRE',): - # il faut tester si la valeur du parametre est un entier - return self.is_entier(valeur.valeur) - else: - print "Objet non reconnu dans is_reel %s" %`valeur` - return 0 - elif type(valeur) not in (types.IntType,types.LongType): - # ce n'est pas un entier - return 0 - else: - return 1 - - def is_object_from(self,objet,classe): - """ - Retourne 1 si valeur est un objet de la classe classe ou d'une - sous-classe de classe, 0 sinon - """ - if type(objet) != types.InstanceType : - return 0 - if not objet.__class__ == classe and not issubclass(objet.__class__,classe): - return 0 - else: - return 1 - - def get_valid(self): - if hasattr(self,'valid'): - return self.valid - else: - self.valid=None - return None - - def set_valid(self,valid): - old_valid=self.get_valid() - self.valid = valid - self.state = 'unchanged' - if not old_valid or old_valid != self.valid : - self.init_modif_up() - - def isvalid(self,cr='non'): - """ - Cette méthode retourne un indicateur de validité de l'objet de type MCSIMP - - - 0 si l'objet est invalide - - 1 si l'objet est valide - - Le paramètre cr permet de paramétrer le traitement. Si cr == 'oui' - la méthode construit également un comte-rendu de validation - dans self.cr qui doit avoir été créé préalablement. - """ - if self.state == 'unchanged': - return self.valid - else: - v=self.valeur - valid = 1 - # verifiaction presence - if self.isoblig() and v == None : - if cr == 'oui' : - self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé"))) - valid = 0 - - if v is None: - valid=0 - if cr == 'oui' : - self.cr.fatal("None n'est pas une valeur autorisée") - else: - # type,into ... - valid = self.verif_type(val=v,cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr) - # - # On verifie les validateurs s'il y en a et si necessaire (valid == 1) - # - if valid and self.definition.validators and not self.definition.validators.verif(self.valeur): - if cr == 'oui' : - self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info()))) - valid=0 - # fin des validateurs - # - - self.set_valid(valid) - return self.valid - - def verif_into(self,cr='non'): - """ - Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs - donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris - entre val_min et val_max - """ - if self.definition.into == None : - #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle) - if type(self.valeur)==types.TupleType : - test = 1 - for val in self.valeur : - if type(val)!=types.StringType and type(val)!=types.InstanceType: - test = test*self.isinintervalle(val,cr=cr) - return test - else : - val = self.valeur - if type(val)!=types.StringType and type(val)!=types.InstanceType: - return self.isinintervalle(self.valeur,cr=cr) - else : - return 1 - else : - # on est dans le cas d'un ensemble discret de valeurs possibles (into) - # PN : pour résoudre le pb du copier /coller de la liste Ordonnee - # if type(self.valeur) == types.TupleType : - if type(self.valeur) in (types.ListType,types.TupleType) : - for e in self.valeur: - if e not in self.definition.into: - if cr=='oui': - self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom))) - return 0 - else: - if self.valeur == None or self.valeur not in self.definition.into: - if cr=='oui': - self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom))) - return 0 - return 1 - diff --git a/Ihm/I_OBJECT.py b/Ihm/I_OBJECT.py index db8158fa..728b6355 100644 --- a/Ihm/I_OBJECT.py +++ b/Ihm/I_OBJECT.py @@ -117,13 +117,6 @@ class OBJECT: else: return [string.strip(self.nom)] - def reparent(self,parent): - """ - Cette methode sert a reinitialiser la parente de l'objet - """ - self.parent=parent - self.jdc=parent.jdc - def get_fr(self): """ Retourne la chaine d'aide contenue dans le catalogue @@ -134,4 +127,3 @@ class OBJECT: except: return '' - diff --git a/Ihm/I_PROC_ETAPE.py b/Ihm/I_PROC_ETAPE.py index b3fa648e..a99cd215 100644 --- a/Ihm/I_PROC_ETAPE.py +++ b/Ihm/I_PROC_ETAPE.py @@ -86,29 +86,3 @@ class PROC_ETAPE(I_ETAPE.ETAPE): self.state="unchanged" self.valid=0 - def Build_sd_old(self): - """ - Cette methode applique la fonction op_init au contexte du parent - et lance l'exécution en cas de traitement commande par commande - Elle doit retourner le concept produit qui pour une PROC est toujours None - En cas d'erreur, elle leve une exception : AsException ou EOFError - """ - if not self.isactif():return - try: - if self.parent: - if type(self.definition.op_init) == types.FunctionType: - apply(self.definition.op_init,(self,self.parent.g_context)) - else: - pass - if self.jdc.par_lot == "NON" : - self.Execute() - except AsException,e: - raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], - 'fichier : ',self.appel[1],e) - except EOFError: - raise - except : - l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) - raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], - 'fichier : ',self.appel[1]+'\n', - string.join(l)) diff --git a/Ihm/I_VALIDATOR.py b/Ihm/I_VALIDATOR.py index 92c93300..0b8645e5 100644 --- a/Ihm/I_VALIDATOR.py +++ b/Ihm/I_VALIDATOR.py @@ -10,423 +10,28 @@ """ import types -import Noyau.N_VALIDATOR class Valid: """ Cette classe est la classe mere de toutes les classes complémentaires que l'on trouve dans Ihm. - Elle porte les comportements par défaut des méthodes des validateurs. """ - 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 des vérifications - sur la liste elle meme et non sur ses items, la méthode - doit retourner une chaine vide. - """ - return " " +class ListVal(Valid):pass - def aide(self): - """ - Cette methode retourne une chaine de caractère qui permet à EFICAS 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() +class RangeVal(ListVal):pass - 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 " " +class CardVal(Valid):pass - 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 +class PairVal(ListVal):pass - 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 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_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 get_into(self,liste_courante=None,into_courant=None): - """ - Cette méthode retourne la liste de choix proposée par le validateur. Si le validateur ne propose - pas de liste de choix, la méthode retourne None. - L'argument d'entrée liste_courante, s'il est différent de None, donne la liste des choix déjà - effectués par l'utilisateur. Dans ce cas, la méthode get_into doit calculer la liste des choix - en en tenant compte. Par exemple, si le validateur n'autorise pas les répétitions, la liste des - choix retournée ne doit pas contenir les choix déjà contenus dans liste_courante. - L'argument d'entrée into_courant, s'il est différent de None, donne la liste des choix proposés - par d'autres validateurs. Dans ce cas, la méthode get_into doit calculer la liste des choix à retourner - en se limitant à cette liste initiale. Par exemple, si into_courant vaut (1,2,3) et que le validateur - propose la liste de choix (3,4,5), la méthode ne doit retourner que (3,). - - La méthode get_into peut retourner une liste vide [], ce qui veut dire qu'il n'y a pas (ou plus) de choix possible - Cette situation peut etre normale : l''utilisateur a utilisé tous les choix, ou résulter d'une incohérence - des validateurs : choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de faire la différence entre - ces deux situations. - """ - return into_courant - - def is_eval(self,valeur): - """ - Cette méthode indique si valeur est un objet de type EVAL ou autre - que l'on ne cherchera pas à evaluer et qui doit etre considere comme toujours valide - Si c'est un objet de ce type elle retourne la valeur 1 sinon la valeur 0 - """ - if type(valeur) == types.InstanceType : - if hasattr(valeur,'__class__'): - if valeur.__class__.__name__ in ('EVAL','entier','reel','chaine','complexe','liste','PARAMETRE_EVAL') : - return 1 - return 0 - - def is_param(self,valeur): - """ - Cette méthode indique si valeur est un objet de type PARAMETRE - dont on cherchera à evaluer la valeur (valeur.valeur) - """ - if type(valeur) == types.InstanceType : - if valeur.__class__.__name__ in ('PARAMETRE',): - return 1 - return 0 - - def is_unknown(self,valeur): - """ - Cette méthode indique si valeur est un objet de type inconnu - c'est à dire ni de type EVAL ni de type PARAMETRE - """ - if type(valeur) == types.InstanceType : - if not self.is_eval(valeur) and not self.is_param(valeur): - return 1 - return 0 - - def surcharge_verif(self,methode_verif_initiale,valeur): - if type(valeur) == types.InstanceType : - #CCAR: pour le moment on fait comme dans is_entier de V_MCSIMP.py - # mais il serait préférable d'appeler une méthode de valeur : valeur.AsType() - # qui donnerait le type générique de l'objet. - # Pour un objet de "type" entier on obtiendrait par exemple 'I' - if valeur.__class__.__name__ in ('EVAL','entier','reel','chaine','complexe','liste','PARAMETRE_EVAL') : - # On ne vérifie pas le type d'un EVAL ou d'un objet de classe entier, .... C'est toujours valide - return 1 - elif valeur.__class__.__name__ in ('PARAMETRE',): - # Dans le cas d'un parametre, il faut tester si la valeur du parametre est un entier - valeur=valeur.valeur - else: - # Objet inconnu : invalide - print "Objet non reconnu dans surcharge_verif : %s" %`valeur` - return 0 - - return methode_verif_initiale(self,valeur) - -class FunctionVal(Valid):pass - -class OrVal(Valid): - def verif_item(self,valeur): - for validator in self.validators: - v=validator.verif_item(valeur) - if v : - return 1 - return 0 - - 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 attende une liste. - """ - for validator in self.validators: - v=validator.is_list() - if v : - return 1 - return 0 - - 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): - def info(self): - return "\n et ".join([v.info() for v in self.validators]) - - def info_erreur_item(self): - chaine="" - a=1 - for v in self.validators: - if v.info_erreur_item() != " " : - if a==1: - chaine=v.info_erreur_item() - a=0 - else: - chaine=chaine+" \n et "+v.info_erreur_item() - return chaine - - def info_erreur_liste(self): - a=1 - for v in self.validators: - if v.info_erreur_liste() != " " : - if a==1: - chaine=v.info_erreur_liste() - a=0 - else: - chaine=chaine+" \n et "+v.info_erreur_liste() - return chaine - - def verif_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 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): - return into_courant - return into_courant - -class CardVal(Valid): - def info(self): - return "longueur de liste comprise entre %s et %s" % (self.min,self.max) - - def is_list(self): - if self.max == '**' or self.max > 1: - return 1 - else: - return 0 - - def verif_item(self,valeur): - 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 - - 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 info_erreur_liste(self): - return "La cardinalité de la liste doit être comprise entre %s et %s" % (self.min,self.max) - -class ListVal(Valid): - 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 - -class EnumVal(ListVal): - 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) - return liste_choix - - def info_erreur_item(self): - return "La valeur n'est pas dans la liste des choix possibles" +class EnumVal(ListVal):pass -class LongStr(ListVal): - def info_erreur_item(self): - return "Longueur de la chaine incorrecte" +class NoRepeat(ListVal):pass - def verif_item(self,valeur): - low=self.low - high=self.high - if valeur[0]=="'" and valeur[-1]=="'" : - low=low+2 - high=high+2 - if len(valeur) < low :return 0 - if len(valeur) > high:return 0 - return 1 - -class RangeVal(ListVal): - def verif_item(self,valeur): - if valeur < self.low :return 0 - if valeur > self.high:return 0 - return 1 +class LongStr(ListVal):pass - def info_erreur_item(self) : - return "La valeur doit être comprise entre %s et %s" % (self.low,self.high) +class OrdList(ListVal):pass CoercableFuncs = { types.IntType: int, types.LongType: long, @@ -434,130 +39,13 @@ CoercableFuncs = { types.IntType: int, types.ComplexType: complex, types.UnicodeType: unicode } -class TypeVal(ListVal): - """ - 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. - """ - def __init__(self, aType): - 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 +class TypeVal(ListVal):pass - def identity ( self, value ): - if type( value ) == self.aType: - return value - raise ValError +class InstanceVal(ListVal):pass - def verif(self,valeur): - if type(valeur) in (types.ListType,types.TupleType): - for val in valeur: - valid=self.verif_item(val) - if valid == 0:return 0 - return 1 - else: - return self.verif_item(valeur) - - def verif_item(self,valeur): - try: - self.coerce(valeur) - except: - return 0 - return 1 - -class PairVal(ListVal): - - def info_erreur_item(self): - return "La valeur saisie doit être paire" - - #ATTENTION METHODE SURCHARGEE: a resorber dans une future version - def verif_item(self,valeur): - if self.is_eval(valeur): - return 1 - elif self.is_param(valeur): - valeur=valeur.valeur - elif self.is_unknown(valeur): - return 0 - return valeur % 2 == 0 - - def verif(self,valeur): - if self.is_param(valeur): - valeur=valeur.valeur - if type(valeur) in (types.ListType,types.TupleType): - for val in valeur: - if not self.verif_item(val): - return 0 - return 1 - else: - return self.verif_item(valeur) - - def verif_old(self,valeur): - print "Ihm.I_MCSIMP.PairVal.verif: ",valeur - return self.surcharge_verif(Noyau.N_VALIDATOR.PairVal.verif,valeur) - -class InstanceVal(ListVal): - def verif_item(self,valeur): - if not isinstance(valeur,self.aClass): return 0 - return 1 - -class NoRepeat(ListVal): - def info(self): - return "pas de presence de doublon dans la liste" - - def info_erreur_liste(self): - return "Les doublons ne sont pas permis" - - def verif_item(self,valeur): - return 1 +class FunctionVal(Valid):pass - 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: - return 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 OrdList(ListVal): - def verif_item(self,valeur): - return 1 +class OrVal(Valid):pass - 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 AndVal(Valid):pass - def info_erreur_liste(self) : - return "La liste doit être en ordre "+self.ord -