From: eficas <> Date: Wed, 6 Nov 2002 17:46:09 +0000 (+0000) Subject: CCAR: Modified Files: X-Git-Tag: CC_param_poursuite~375 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=8001ff4db171debb2a4e3d963af402e87e80b46e;p=modules%2Feficas.git CCAR: Modified Files: CCAR: I_ETAPE.py I_FORM_ETAPE.py I_JDC.py I_MACRO_ETAPE.py CCAR: I_MCCOMPO.py I_MCLIST.py I_MCSIMP.py I_PROC_ETAPE.py CCAR: ---------------------------------------------------------------------- CCAR : developpement pour traiter correctement l'insertion et la destruction des macros avec etapes et concepts inclus. Ces INCLUDEs sont evalués dans un JDC auxiliaire avant d'etre insérées définitivement dans la macro apres verification. --- diff --git a/Ihm/I_ETAPE.py b/Ihm/I_ETAPE.py index 865f2378..5ccb189e 100644 --- a/Ihm/I_ETAPE.py +++ b/Ihm/I_ETAPE.py @@ -20,6 +20,7 @@ """ """ # Modules Python +import sys import string,types from copy import copy @@ -40,10 +41,11 @@ class ETAPE(I_MCCOMPO.MCCOMPO): def get_sdname(self): if CONTEXT.debug : print "SDNAME ",self.reuse,self.sd,self.sd.get_name() + sdname='' if self.reuse != None: sdname= self.reuse.get_name() else: - sdname=self.sd.get_name() + if self.sd:sdname=self.sd.get_name() if string.find(sdname,'sansnom') != -1 or string.find(sdname,'SD_') != -1: # dans le cas où la SD est 'sansnom' ou 'SD_' on retourne la chaîne vide return '' @@ -59,7 +61,6 @@ class ETAPE(I_MCCOMPO.MCCOMPO): """ Met l'état de l'étape à : modifié Propage la modification au parent - Si la fonction op_init existe, l'active """ # Une action # doit etre realisée apres init_modif et la validite reevaluée @@ -76,11 +77,10 @@ class ETAPE(I_MCCOMPO.MCCOMPO): ex : INCLUDE et POURSUITE """ if self.isvalid() : - if type(self.definition.op_init) == types.FunctionType : - # XXX Normalement en mode editeur g_context ne peut pas etre utilisé - apply(self.definition.op_init,(self,self.parent.g_context)) - self.state = 'modified' - + d=self.parent.get_contexte_apres(self) + if self.parent: + self.parent.fin_modif() + def nomme_sd(self,nom) : """ Cette méthode a pour fonction de donner un nom (nom) au concept @@ -190,9 +190,9 @@ class ETAPE(I_MCCOMPO.MCCOMPO): Il faut ajouter la sd si elle existe au contexte global du JDC et à la liste des sd """ + if self.actif:return self.actif = 1 if not self.sd : return - # XXX Pourquoi faut-il faire ce qui suit ??? par defaut les etapes sont actives try: self.jdc.append_sdprod(self.sd) except: @@ -209,6 +209,31 @@ class ETAPE(I_MCCOMPO.MCCOMPO): self.jdc.del_sdprod(self.sd) self.jdc.delete_concept_after_etape(self,self.sd) + def control_sdprods(self,d): + """ + Cette methode doit updater le contexte fournit par + l'appelant en argument (d) en fonction de sa definition + tout en verifiant que ses concepts produits ne sont pas + deja definis dans le contexte + """ + if type(self.definition.op_init) == types.FunctionType: + apply(self.definition.op_init,(self,d)) + if self.sd: + if d.has_key(self.sd.nom): + # Le concept est deja defini + if self.reuse and self.reuse is d[self.sd.nom]: + # Le concept est reutilise : situation normale + pass + else: + # Redefinition du concept, on l'annule + #XXX on pourrait simplement annuler son nom pour conserver les objets + # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??) + self.sd=self.reuse=self.sdnom=None + self.init_modif() + else: + # Le concept n'est pas defini, on peut updater d + d[self.sd.nom]=self.sd + def supprime_sdprods(self): """ Fonction: @@ -217,8 +242,6 @@ class ETAPE(I_MCCOMPO.MCCOMPO): Une procedure n'en a aucun Une macro en a en général plus d'un """ - # XXX pour les macros il faudrait peut etre aussi - # supprimer les concepts a droite du = ??? if not self.is_reentrant() : # l'étape n'est pas réentrante # le concept retourné par l'étape est à supprimer car il était @@ -244,6 +267,22 @@ class ETAPE(I_MCCOMPO.MCCOMPO): for child in self.mc_liste : child.delete_concept(sd) + def replace_concept(self,old_sd,sd): + """ + Inputs : + old_sd=concept remplace + sd = nouveau concept + Fonction : + Mettre a jour les mots cles de l etape et eventuellement + le concept produit si reuse + suite au remplacement du concept old_sd + """ + if self.reuse and self.reuse == old_sd: + self.sd=self.reuse=sd + self.init_modif() + for child in self.mc_liste : + child.replace_concept(old_sd,sd) + def make_register(self): """ Initialise les attributs jdc, id, niveau et réalise les @@ -392,8 +431,10 @@ class ETAPE(I_MCCOMPO.MCCOMPO): # 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 + #raise AsException("Etape ",self.nom,'ligne : ',self.appel[0], # 'fichier : ',self.appel[1],e) except EOFError: diff --git a/Ihm/I_FORM_ETAPE.py b/Ihm/I_FORM_ETAPE.py index 80689be4..b76b4b5a 100644 --- a/Ihm/I_FORM_ETAPE.py +++ b/Ihm/I_FORM_ETAPE.py @@ -262,7 +262,7 @@ class FORM_ETAPE(MACRO_ETAPE): Inputs : sd=concept detruit Fonction : - Mettre a jour les mos cles de l etape et eventuellement le concept produit si reuse + Mettre a jour les mots cles de l etape et eventuellement le concept produit si reuse suite à la disparition du concept sd Seuls les mots cles simples MCSIMP font un traitement autre que de transmettre aux fils, sauf les objets FORM_ETAPE qui doivent vérifier que le concept détruit n'est pas @@ -270,3 +270,14 @@ class FORM_ETAPE(MACRO_ETAPE): """ self.init_modif() + def replace_concept(self,old_sd,sd): + """ + Inputs : + old_sd=concept remplace + sd = nouveau concept + Fonction : + Les objets FORM_ETAPE devraient vérifier que le concept remplacé n'est pas + utilisé dans le corps de la fonction + """ + self.init_modif() + diff --git a/Ihm/I_JDC.py b/Ihm/I_JDC.py index 125fb617..3b895351 100644 --- a/Ihm/I_JDC.py +++ b/Ihm/I_JDC.py @@ -216,6 +216,57 @@ 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 + 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 + """ + if not etape: return self.get_contexte_avant(etape) + + d=self.get_contexte_avant(etape) + if etape.isactif():etape.update_context(d) + self.index_etape_courante=self.index_etape_courante+1 + return d + def active_etapes(self): """ Cette méthode a pour fonction de désactiver les étapes qui doivent @@ -245,6 +296,10 @@ class JDC(I_OBJECT.OBJECT): un jeu de commandes """ self.init_modif() + # On memorise le contexte avant l'etape a supprimer + d=self.get_contexte_avant(etape) + index_etape=self.etapes.index(etape) + self.etapes.remove(etape) if etape.niveau is not self: # Dans ce cas l'étape est enregistrée dans un niveau @@ -253,25 +308,13 @@ class JDC(I_OBJECT.OBJECT): etape.supprime_sdprods() self.active_etapes() - def del_sdprod(self,sd): - """ - Supprime la SD sd de la liste des sd et des dictionnaires de contexte - """ - if sd in self.sds : self.sds.remove(sd) - if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom] - - def delete_concept(self,sd): - """ - Inputs : - sd=concept detruit - Fonction : - Mettre a jour les etapes du JDC suite à la disparition du - concept sd - Seuls les mots cles simples MCSIMP font un traitement autre - que de transmettre aux fils - """ - for etape in self.etapes : - etape.delete_concept(sd) + # Apres suppression de l'etape il faut controler que les etapes + # suivantes ne produisent pas des concepts DETRUITS dans op_init de etape + for e in self.etapes[index_etape:]: + e.control_sdprods(d) + + self.reset_context() + self.fin_modif() def analyse(self): self.compile() @@ -368,17 +411,6 @@ class JDC(I_OBJECT.OBJECT): if self.appli: self.appli.send_message(message) -#XXX ne semble pas servir pour JDC -# def reevalue_sd_jdc(self): - #""" - #Avec la liste des SD qui ont été supprimées, propage la disparition de ces - #SD dans toutes les étapes et descendants - #""" - #l_sd = self.diff_contextes() - #if len(l_sd) == 0 : return - #for sd in l_sd: - #self.jdc.delete_concept(sd) - def init_modif(self): """ Méthode appelée au moment où une modification va être faite afin de @@ -387,6 +419,7 @@ class JDC(I_OBJECT.OBJECT): self.state = 'modified' def fin_modif(self): + self.isvalid() pass def get_liste_mc_inconnus(self): @@ -423,6 +456,7 @@ class JDC(I_OBJECT.OBJECT): 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 @@ -435,30 +469,34 @@ class JDC(I_OBJECT.OBJECT): """ return [] - def NommerSdprod(self,sd,sdnom): + def NommerSdprod(self,sd,sdnom,restrict='non'): """ - Nomme la SD apres avoir verifie que le nommage est possible : nom - non utilise + 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 une indication de l'étape - # traitée. Pour le moment, il n'y a pas de moyen de le faire : ajouter - # un attribut dans le JDC ??? + # 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.g_context.get(sdnom,None) + 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.g_context[sdnom]=sd + self.sds_dict[sdnom]=sd sd.nom=sdnom def set_etape_context(self,etape): @@ -477,6 +515,14 @@ class JDC(I_OBJECT.OBJECT): self.current_context={} self.index_etape_courante=0 + def del_sdprod(self,sd): + """ + Supprime la SD sd de la liste des sd et des dictionnaires de contexte + """ + if sd in self.sds : self.sds.remove(sd) + if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom] + if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom] + def del_param(self,param): """ Supprime le paramètre param de la liste des paramètres @@ -493,3 +539,101 @@ class JDC(I_OBJECT.OBJECT): if fonction in self.fonctions : self.fonctions.remove(fonction) if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom] + def append_sdprod(self,sd): + """ + Ajoute la SD sd à la liste des sd en vérifiant au préalable qu'une SD de + même nom n'existe pas déjà + """ + if sd == None or sd.nom == None:return + + o=self.sds_dict.get(sd.nom,None) + if isinstance(o,ASSD): + raise AsException("Nom de concept deja defini : %s" % sd.nom) + self.sds_dict[sd.nom]=sd + self.g_context[sd.nom] = sd + if sd not in self.sds : self.sds.append(sd) + + def append_param(self,param): + """ + Ajoute le paramètre param à la liste des params + et au contexte global + """ + # il faudrait vérifier qu'un paramètre de même nom n'existe pas déjà !!! + if param not in self.params : self.params.append(param) + self.g_context[param.nom]=param + + def append_fonction(self,fonction): + """ + Ajoute la fonction fonction à la liste des fonctions + et au contexte global + """ + # il faudrait vérifier qu'une fonction de même nom n'existe pas déjà !!! + 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 : + sd=concept detruit + Fonction : + Mettre a jour les etapes du JDC suite à la disparition du + concept sd + Seuls les mots cles simples MCSIMP font un traitement autre + que de transmettre aux fils + """ + for etape in self.etapes : + etape.delete_concept(sd) + + def replace_concept_after_etape(self,etape,old_sd,sd): + """ + Met à jour les étapes du JDC qui sont après etape en fonction + du remplacement 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.replace_concept(old_sd,sd) + + def dump_state(self): + print "dump_state" + print "JDC.state: ",self.state + for etape in self.etapes : + print etape.nom+".state: ",etape.state + +#ATTENTION cette methode surcharge la methode du package Validation : a reintegrer + def isvalid(self,cr='non'): + """ + Méthode booléenne qui retourne 0 si le JDC est invalide, 1 sinon + """ + # FR : on prend en compte l'état du JDC ('unchanged','modified','undetermined') + # afin d'accélérer le test de validité du JDC + if self.state == 'unchanged': + return self.valid + else: + valid = 1 + texte,test = self.verif_regles() + if test == 0: + if cr == 'oui': self.cr.fatal(string.strip(texte)) + valid = 0 + if valid : + for e in self.etapes: + if not e.isactif() : continue + if not e.isvalid(): + valid = 0 + break + self.state="unchanged" + self.valid = valid + return self.valid + diff --git a/Ihm/I_MACRO_ETAPE.py b/Ihm/I_MACRO_ETAPE.py index 1fd95f5e..5c00db69 100644 --- a/Ihm/I_MACRO_ETAPE.py +++ b/Ihm/I_MACRO_ETAPE.py @@ -20,6 +20,7 @@ """ """ # Modules Python +import sys import traceback,types,string # Modules Eficas @@ -27,7 +28,7 @@ import I_ETAPE from Noyau.N_ASSD import ASSD # import rajoutés suite à l'ajout de Build_sd --> à résorber -import Noyau +import Noyau, Validation.V_MACRO_ETAPE from Noyau import N_Exception from Noyau.N_Exception import AsException # fin import à résorber @@ -35,8 +36,6 @@ from Noyau.N_Exception import AsException class MACRO_ETAPE(I_ETAPE.ETAPE): def __init__(self): - # XXX CCAR : ne suis pas certain que typret doive etre - # initialise à None (a verifier) self.typret=None def get_sdprods(self,nom_sd): @@ -44,73 +43,90 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): Fonction : retourne le concept produit par l etape de nom nom_sd s il existe sinon None """ - if self.sd: - if self.sd.nom == nom_sd: - return self.sd + if self.sd and self.sd.nom == nom_sd :return self.sd for co in self.sdprods: - if co.nom==nom_sd:return co + if co.nom == nom_sd:return co + if type(self.definition.op_init) == types.FunctionType: + d={} + apply(self.definition.op_init,(self,d)) + return d.get(nom_sd,None) return None - def make_contexte(self,fichier,text): - """ - Cette méthode sert à créer un contexte en interprétant un texte source - Python - """ - # on récupère le contexte d'un nouveau jdc dans lequel on interprete text - contexte = self.get_contexte_jdc(fichier,text) - if contexte == None : - raise Exception("Impossible de relire le fichier") - else: - self.g_context = contexte - if hasattr(self,'contexte_fichier_init'): - self.old_contexte_fichier_init = self.contexte_fichier_init - self.contexte_fichier_init = contexte - # XXX la validité ne doit pas etre forcée à 1. Que faut-il faire exactement ??? - self.init_modif() - #self.valid = 1 - #self.state = 'unchanged' - def get_contexte_jdc(self,fichier,text): """ Interprète text comme un texte de jdc et retourne le contexte final cad le dictionnaire des sd disponibles à la dernière étape Si text n'est pas un texte de jdc valide, retourne None + ou leve une exception --> utilisée par ops.POURSUITE et INCLUDE """ try: - # on essaie de créer un objet JDC... + # on essaie de créer un objet JDC auxiliaire avec un contexte initial context_ini = self.parent.get_contexte_avant(self) + # Indispensable avant de creer un nouveau JDC CONTEXT.unset_current_step() - j=self.jdc.definition(procedure=text,cata=self.jdc.cata, - nom=fichier, - context_ini = context_ini, - appli=self.jdc.appli) + args=self.jdc.args + prefix_include=None + if hasattr(self,'prefix'): + prefix_include=self.prefix + + j=self.JdC_aux( procedure=text,cata=self.jdc.cata, + nom=fichier, + context_ini = context_ini, + appli=self.jdc.appli, + jdc_pere=self.jdc,etape_include=self, + prefix_include=prefix_include,**args) + j.analyse() - # XXX en passant par un jdc auxiliaire, on risque de rendre les etapes inactives - # on les force dans l'etat actif - for etape in j.etapes: - etape.active() except: traceback.print_exc() + # On force le contexte (etape courante) à self + CONTEXT.unset_current_step() + CONTEXT.set_current_step(self) return None - CONTEXT.set_current_step(self) + if not j.cr.estvide(): - raise Exception("Impossible de relire le fichier\n"+str(j.cr)) + # On force le contexte (etape courante) à self + CONTEXT.unset_current_step() + CONTEXT.set_current_step(self) + # Erreurs dans l'INCLUDE. On garde la memoire du fichier mais on n'insere pas les concepts + # et les etapes. Ce traitement doit etre fait par l'appelant qui recoit l'exception + raise Exception("Impossible de relire le fichier\n"+str(j.cr)) + + cr=j.report() + if not cr.estvide(): + # On force le contexte (etape courante) à self + CONTEXT.unset_current_step() + CONTEXT.set_current_step(self) + raise Exception("Le fichier include contient des erreurs\n"+str(j.cr)) + + # Cette verification n'est plus necessaire elle est integree dans le JDC_INCLUDE + #self.verif_contexte(j_context) - #XXX la validité d'un source inclus n'est pas identique à celle d'un JDC complet - # impossible de la tester en dehors du JDC d'accueil - #cr=j.report() - #if not cr.estvide(): - # raise Exception("Le fichier contient des erreurs\n"+str(j.cr)) + # On recupere le contexte apres la derniere etape j_context=j.get_contexte_avant(None) - # XXX j.g_context doit donner le meme résultat - # On retourne le contexte apres la derniere etape - # XXX j.supprime() ??? - self.verif_contexte(j_context) - # Le contexte est acceptable. On récupère les étapes internes (pour validation) + + # On remplit le dictionnaire des concepts produits inclus + # en retirant les concepts présents dans le contexte initial + self.g_context.clear() + for k,v in j_context.items(): + if not context_ini.has_key(k) or context_ini[k] != v: + self.g_context[k]=v + + # On récupère les étapes internes (pour validation) self.etapes=j.etapes + + # ainsi que le contexte courant + self.current_context=j.current_context + self.index_etape_courante=j.index_etape_courante + + # XXX j.supprime() ??? + # On force le contexte (etape courante) à self + CONTEXT.unset_current_step() + CONTEXT.set_current_step(self) + return j_context def verif_contexte(self,context): @@ -128,27 +144,71 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): def reevalue_sd_jdc(self): """ Avec la liste des SD qui ont été supprimées, propage la - disparition de ces SD dans totues les étapes et descendants + disparition de ces SD dans toutes les étapes et descendants """ - l_sd = self.diff_contextes() - if len(l_sd) == 0 : return - for sd in l_sd: - self.jdc.delete_concept(sd) + l_sd_supp,l_sd_repl = self.diff_contextes() + for sd in l_sd_supp: + self.parent.delete_concept_after_etape(self,sd) + for old_sd,sd in l_sd_repl: + self.parent.replace_concept_after_etape(self,old_sd,sd) def diff_contextes(self): """ Réalise la différence entre les 2 contextes old_contexte_fichier_init et contexte_fichier_init - cad retourne la liste des sd qui ont disparu + cad retourne la liste des sd qui ont disparu ou ne derivent pas de la meme classe + et des sd qui ont ete remplacees """ - if not hasattr(self,'old_contexte_fichier_init'):return [] + if not hasattr(self,'old_contexte_fichier_init'):return [],[] l_sd_suppressed = [] + l_sd_replaced = [] for old_key in self.old_contexte_fichier_init.keys(): if not self.contexte_fichier_init.has_key(old_key): if isinstance(self.old_contexte_fichier_init[old_key],ASSD): l_sd_suppressed.append(self.old_contexte_fichier_init[old_key]) - return l_sd_suppressed + else: + if isinstance(self.old_contexte_fichier_init[old_key],ASSD): + # Un concept de meme nom existe + old_class=self.old_contexte_fichier_init[old_key].__class__ + if not isinstance(self.contexte_fichier_init[old_key],old_class): + # S'il n'est pas d'une classe derivee, on le supprime + l_sd_suppressed.append(self.old_contexte_fichier_init[old_key]) + else: + l_sd_replaced.append((self.old_contexte_fichier_init[old_key],self.contexte_fichier_init[old_key])) + return l_sd_suppressed,l_sd_replaced + def control_sdprods(self,d): + """ + Cette methode doit updater le contexte fournit par + l'appelant en argument (d) en fonction de sa definition + tout en verifiant que ses concepts produits ne sont pas + deja definis dans le contexte + """ + if type(self.definition.op_init) == types.FunctionType: + apply(self.definition.op_init,(self,d)) + if self.sd: + if d.has_key(self.sd.nom): + # Le concept est deja defini + if self.reuse and self.reuse is d[self.sd.nom]: + # Le concept est reutilise : situation normale + pass + else: + # Redefinition du concept, on l'annule + #XXX on pourrait simplement annuler son nom pour conserver les objets + # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??) + self.sd=self.reuse=self.sdnom=None + self.init_modif() + else: + # Le concept n'est pas defini, on peut updater d + d[self.sd.nom]=self.sd + # On verifie les concepts a droite du signe = + for co in self.sdprods: + if d.has_key(co.nom) and co is not d[co.nom] : + self.delete_concept(co) + else: + d[co.nom]=co + + def supprime_sdprods(self): """ Fonction: @@ -171,12 +231,12 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): # Si la macro a des etapes et des concepts inclus, on les detruit for nom_sd,co in self.g_context.items(): if not isinstance(co,ASSD):continue - print "Delete: ",self.nom,co.nom self.parent.del_sdprod(co) self.parent.delete_concept(co) # On met g_context à blanc self.g_context={} +#ATTENTION : cette methode surcharge celle de Noyau (a garder en synchro) def Build_sd(self,nom): """ Construit le concept produit de l'opérateur. Deux cas @@ -220,8 +280,10 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): # 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], @@ -234,3 +296,175 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): 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 + Python + """ + # on récupère le contexte d'un nouveau jdc dans lequel on interprete text + contexte = self.get_contexte_jdc(fichier,text) + if contexte == None : + raise Exception("Impossible de construire le jeu de commandes correspondant au fichier") + else: + # Pour les macros de type include : INCLUDE, INCLUDE_MATERIAU et POURSUITE + # l'attribut g_context est un dictionnaire qui contient les concepts produits par inclusion + # l'attribut contexte_fichier_init est un dictionnaire qui contient les concepts produits + # en sortie de macro. g_context est obtenu en retirant de contexte_fichier_init les concepts + # existants en debut de macro contenus dans context_ini (dans get_contexte_jdc) + # g_context est utilisé pour avoir les concepts produits par la macro + # contexte_fichier_init est utilisé pour avoir les concepts supprimés par la macro + self.contexte_fichier_init = contexte + + def reevalue_fichier_init(self): + """Recalcule les concepts produits par le fichier enregistre""" + old_context=self.contexte_fichier_init + try: + self.make_contexte_include(self.fichier_ini ,self.fichier_text) + except: + l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1]) + self.fichier_err = string.join(l) + self.etapes=[] + self.g_context={} + + self.old_contexte_fichier_init=old_context + self.contexte_fichier_init={} + self.reevalue_sd_jdc() + return + + # L'evaluation s'est bien passee + self.fichier_err = None + self.old_contexte_fichier_init=old_context + self.reevalue_sd_jdc() + + 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(fic_origine=self.parent.nom) + # On memorise le fichier retourne + self.fichier_ini = f + self.fichier_text = text + 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" + else: + self.fichier_err=None + + if self.fichier_err is not None: raise Exception(self.fichier_err) + + try: + self.make_contexte_include(self.fichier_ini,self.fichier_text) + 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.g_context={} + self.etapes=[] + 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 + if self.fichier_err is not None: raise Exception(self.fichier_err) + + +#ATTENTION : 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 + Cette methode est appelee par la fonction sd_prod de la macro INCLUDE + Si l'INCLUDE est invalide, la methode doit produire une exception + Sinon on retourne None. Les concepts produits par l'INCLUDE sont + pris en compte par le JDC parent lors du calcul du contexte (appel de ???) + """ + + # On supprime l'attribut unite qui bloque l'evaluation du source de l'INCLUDE + # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini + del self.unite + # Si unite n'a pas de valeur, l'etape est forcement invalide. On peut retourner None + if not unite : return + + if not hasattr(self,'fichier_ini') : + # Si le fichier n'est pas defini on le demande + f,text=self.get_file(unite=unite,fic_origine=self.parent.nom) + # On memorise le fichier retourne + self.fichier_ini = f + self.fichier_text = text + self.contexte_fichier_init={} + if f is None: + self.fichier_err="Le fichier INCLUDE n est pas defini" + else: + self.fichier_err=None + import Extensions.jdc_include + self.JdC_aux=Extensions.jdc_include.JdC_include + + if self.fichier_err is not None: raise Exception(self.fichier_err) + + try: + self.make_contexte_include(self.fichier_ini ,self.fichier_text) + 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 inclus", + message="Ce fichier ne sera pas pris en compte\n"+string.join(l) + ) + self.g_context={} + self.etapes=[] + 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.reevalue_fichier_init() + if self.fichier_err is not None: raise Exception(self.fichier_err) + + +#ATTENTION : 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 + en interprétant un texte source Python + Elle est appelee par la fonction sd_prd d'INCLUDE_MATERIAU + """ + # On supprime l'attribut mat qui bloque l'evaluation du source de l'INCLUDE_MATERIAU + # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini + if hasattr(self,'mat'):del self.mat + self.fichier_ini =fichier + self.fichier_text=text + self.fichier_err=None + self.contexte_fichier_init={} + # On specifie la classe a utiliser pour le JDC auxiliaire + import Extensions.jdc_include + self.JdC_aux=Extensions.jdc_include.JdC_include + try: + self.make_contexte_include(self.fichier_ini ,self.fichier_text) + except: + l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1]) + self.g_context={} + self.etapes=[] + self.fichier_err = string.join(l) + self.contexte_fichier_init={} + raise + +#ATTENTION : 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 + # a la reconstruction d'etapes dans le cas d'INCLUDE ou d'INCLUDE_MATERIAU + # Il faut donc positionner le current_step avant l'appel + CONTEXT.unset_current_step() + CONTEXT.set_current_step(self) + valid=Validation.V_MACRO_ETAPE.MACRO_ETAPE.update_sdprod(self,cr=cr) + CONTEXT.unset_current_step() + return valid + diff --git a/Ihm/I_MCCOMPO.py b/Ihm/I_MCCOMPO.py index d7e828ff..fd773d94 100644 --- a/Ihm/I_MCCOMPO.py +++ b/Ihm/I_MCCOMPO.py @@ -309,6 +309,18 @@ class MCCOMPO(I_OBJECT.OBJECT): for child in self.mc_liste : child.delete_concept(sd) + def replace_concept(self,old_sd,sd): + """ + Inputs : + old_sd=concept remplace + sd = nouveau concept + Fonction : + Mettre a jour les fils de l objet suite au remplacement du + concept old_sd + """ + for child in self.mc_liste : + child.replace_concept(old_sd,sd) + def delete_mc_global(self,mc): """ Supprime le mot-clé mc de la liste des mots-clés globaux de l'étape diff --git a/Ihm/I_MCLIST.py b/Ihm/I_MCLIST.py index b9529e33..c201ed25 100644 --- a/Ihm/I_MCLIST.py +++ b/Ihm/I_MCLIST.py @@ -71,6 +71,18 @@ class MCList: for child in self.data : child.delete_concept(sd) + def replace_concept(self,old_sd,sd): + """ + Inputs : + old_sd=concept remplacé + sd=nouveau concept + Fonction : + Mettre a jour les fils de l objet suite au remplacement + du concept old_sd + """ + for child in self.data : + child.replace_concept(old_sd,sd) + def copy(self): """ Réalise la copie d'une MCList diff --git a/Ihm/I_MCSIMP.py b/Ihm/I_MCSIMP.py index ca1bafa3..cbe8d0c2 100644 --- a/Ihm/I_MCSIMP.py +++ b/Ihm/I_MCSIMP.py @@ -200,6 +200,7 @@ class MCSIMP(I_OBJECT.OBJECT): 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 @@ -214,27 +215,30 @@ class MCSIMP(I_OBJECT.OBJECT): except: traceback.print_exc() return 0 - self.val=self.valeur 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.init_modif() + self.fin_modif() return 1 else: return 0 else : # on ne fait aucune vérification ... + self.init_modif() try: self.valeur = eval(new_valeur) self.val = eval(new_valeur) - self.init_modif() + self.fin_modif() return 1 except: self.valeur = new_valeur self.val = new_valeur - self.init_modif() + self.fin_modif() return 1 def eval_valeur(self,new_valeur): @@ -282,6 +286,32 @@ class MCSIMP(I_OBJECT.OBJECT): self.val=None self.init_modif() + def replace_concept(self,old_sd,sd): + """ + Inputs : + old_sd=concept remplacé + sd=nouveau concept + Fonction : + Met a jour la valeur du mot cle simple suite au remplacement + du concept old_sd + """ + if type(self.valeur) == types.TupleType : + if old_sd in self.valeur: + self.valeur=list(self.valeur) + i=self.valeur.index(old_sd) + self.valeur[i]=sd + self.init_modif() + elif type(self.valeur) == types.ListType: + if old_sd in self.valeur: + i=self.valeur.index(old_sd) + self.valeur[i]=sd + self.init_modif() + else: + if self.valeur == old_sd: + self.valeur=sd + self.val=sd + self.init_modif() + def copy(self): """ Retourne une copie de self """ objet = self.makeobjet() @@ -339,9 +369,10 @@ class MCSIMP(I_OBJECT.OBJECT): new_objet = CO(nom_co) CONTEXT.unset_current_step() CONTEXT.set_current_step(cs) + self.init_modif() self.valeur = new_objet self.val = new_objet - self.init_modif() + self.fin_modif() step.reset_context() # On force l'enregistrement de new_objet en tant que concept produit # de la macro en appelant get_type_produit avec force=1 @@ -371,13 +402,16 @@ class MCSIMP(I_OBJECT.OBJECT): else: l.append(sd) self.valeur=l + # Est ce init_modif ou init_modif_up + # Normalement init_modif va avec fin_modif self.init_modif() + self.fin_modif() else: if isinstance(self.valeur,ASSD) : if self.valeur not in l_sd_avant_etape : self.valeur = None self.init_modif() - + self.fin_modif() def get_min_max(self): """ @@ -392,6 +426,48 @@ class MCSIMP(I_OBJECT.OBJECT): """ return self.definition.type +#ATTENTION : toutes les methodes ci apres sont des surcharges du Noyau et de Validation +# Elles doivent etre reintegrees des que possible + + 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: + valid = 1 + if hasattr(self,'valid'): + old_valid = self.valid + else: + old_valid = None + v=self.valeur + # presence + if self.isoblig() and v == None : + if cr == 'oui' : + self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé"))) + valid = 0 + # type,into ... + valid = self.verif_type(cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr) + self.valid = valid + self.state = 'unchanged' + # Si la validité du mot clé a changé, on le signale à l'objet parent + if not old_valid: + self.init_modif_up() + elif old_valid != self.valid : + self.init_modif_up() + return self.valid + diff --git a/Ihm/I_PROC_ETAPE.py b/Ihm/I_PROC_ETAPE.py index 81d6c810..b4ebb72d 100644 --- a/Ihm/I_PROC_ETAPE.py +++ b/Ihm/I_PROC_ETAPE.py @@ -21,7 +21,8 @@ import I_ETAPE # import rajoutés suite à l'ajout de Build_sd --> à résorber -import traceback,types +import sys +import traceback,types,string import Noyau from Noyau import N_Exception from Noyau.N_Exception import AsException @@ -52,6 +53,18 @@ class PROC_ETAPE(I_ETAPE.ETAPE): for child in self.mc_liste : child.delete_concept(sd) + def replace_concept(self,old_sd,sd): + """ + Inputs : + old_sd=concept remplacé + sd=nouveau concept + Fonction : + Mettre a jour les mots cles de l etape + suite au remplacement du concept old_sd + """ + for child in self.mc_liste : + child.replace_concept(old_sd,sd) + def Build_sd(self): """ Cette methode applique la fonction op_init au contexte du parent