Salome HOME
PN :pour notation scientifique
[tools/eficas.git] / Ihm / I_MACRO_ETAPE.py
index 6475b9aea1b9f968b5bfcf979b2847b9de58868d..06f71488ec22181bd27b5c6e1d46fa2924eaf262 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 #            CONFIGURATION MANAGEMENT OF EDF VERSION
 # ======================================================================
 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
@@ -37,11 +38,12 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
 
   def __init__(self):
       self.typret=None
+      self.recorded_units={}
 
   def get_sdprods(self,nom_sd):
     """ 
          Fonction : retourne le concept produit par l etape de nom nom_sd
-                    s il existe sinon None
+         s il existe sinon None
     """
     if self.sd and self.sd.nom == nom_sd :return self.sd
     for co in self.sdprods:
@@ -71,15 +73,27 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
        prefix_include=None
        if hasattr(self,'prefix'):
           prefix_include=self.prefix
+       # ATTENTION : le dictionnaire recorded_units sert à memoriser les unites des 
+       # fichiers inclus. Il est preferable de garder le meme dictionnaire pendant
+       # tout le traitement et de ne pas le reinitialiser brutalement (utiliser 
+       # clear plutot) si on ne veut pas perdre la memoire des unites.
+       # En principe si la memorisation est faite au bon moment il n'est pas necessaire
+       # de prendre cette precaution mais ce n'est pas vrai partout.
+       old_recorded_units=self.recorded_units.copy()
+       self.recorded_units.clear()
 
        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)
+                                prefix_include=prefix_include,
+                                recorded_units=self.recorded_units,
+                                old_recorded_units=old_recorded_units,**args)
 
        j.analyse()
+       # On récupère les étapes internes (pour validation)
+       self.etapes=j.etapes
     except:
        traceback.print_exc()
        # On force le contexte (etape courante) à self
@@ -88,62 +102,52 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
        return None
 
     if not j.cr.estvide():
+       # Erreurs dans l'INCLUDE. On garde la memoire du fichier 
+       # mais on n'insere pas les concepts
        # 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():
+       # L'INCLUDE n'est pas valide.
        # 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)
-
-    # On recupere le contexte apres la derniere etape
-    j_context=j.get_contexte_avant(None)
+    # On recupere le contexte de l'include verifie
+    try:
+       j_context=j.get_verif_contexte()
+    except:
+       CONTEXT.unset_current_step()
+       CONTEXT.set_current_step(self)
+       raise
 
     # On remplit le dictionnaire des concepts produits inclus
     # en retirant les concepts présents dans le  contexte initial
     # On ajoute egalement le concept produit dans le sds_dict du parent
-    # sans verification car on est sur (verification integrée) que le nommage est possible
+    # sans verification car on est sur (verification integrée) que 
+    # le nommage est possible
     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
            self.parent.sds_dict[k]=v
 
-    # On récupère les étapes internes (pour validation)
-    self.etapes=j.etapes
 
-    # ainsi que le contexte courant
+    # On recupere 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
+    # On rétablit le contexte (etape courante) à self
     CONTEXT.unset_current_step()
     CONTEXT.set_current_step(self)
 
     return j_context
 
-  def verif_contexte(self,context):
-     """
-         On verifie que le contexte context peut etre inséré dans le jeu
-         de commandes à la position de self
-     """
-     for nom_sd,sd in context.items():
-        if not isinstance(sd,ASSD):continue
-        if self.parent.get_sd_apres_etape(nom_sd,etape=self):
-           # Il existe un concept apres self => impossible d'inserer
-           raise Exception("Impossible d'inclure le fichier. Un concept de nom " + 
-                           "%s existe déjà dans le jeu de commandes." % nom_sd)
-
   def reevalue_sd_jdc(self):
      """
          Avec la liste des SD qui ont été supprimées, propage la 
@@ -159,8 +163,8 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
      """ 
          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 ou ne derivent pas de la meme classe
-         et des sd qui ont ete remplacees
+         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 [],[]
      l_sd_suppressed = []
@@ -187,6 +191,10 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
           tout en verifiant que ses concepts produits ne sont pas
           deja definis dans le contexte
       """
+      if hasattr(self,"fichier_unite"):
+         self.update_fichier_init(self.fichier_unite)
+         self.init_modif()
+
       if type(self.definition.op_init) == types.FunctionType:
         apply(self.definition.op_init,(self,d))
       if self.sd:
@@ -215,10 +223,10 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
   def supprime_sdprods(self):
       """
           Fonction:
-            Lors d'une destruction d'etape, detruit tous les concepts produits
-            Un opérateur n a qu un concept produit
-            Une procedure n'en a aucun
-            Une macro en a en général plus d'un
+          Lors d'une destruction d'etape, detruit tous les concepts produits
+          Un opérateur n a qu un concept produit
+          Une procedure n'en a aucun
+          Une macro en a en général plus d'un
       """
       if not self.is_reentrant() :
          # l'étape n'est pas réentrante
@@ -239,67 +247,6 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
       # 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 
-        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()
-        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
@@ -327,7 +274,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
       except:
          l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
          self.fichier_err = string.join(l)
-         self.etapes=[]
+         #self.etapes=[]
          self.g_context={}
 
          self.old_contexte_fichier_init=old_context
@@ -340,46 +287,106 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
       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
+  def update_fichier_init(self,unite):
+      """Reevalue le fichier init sans demander (dans la mesure du possible) a l'utilisateur 
+         les noms des fichiers
+         Ceci suppose que les relations entre unites et noms ont été memorisees préalablement
       """
-      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_err=None
+      self.old_contexte_fichier_init=self.contexte_fichier_init
+
+      if unite != self.fichier_unite or not self.parent.recorded_units.has_key(unite):
+         # Changement d'unite ou Nouvelle unite
+         f,text=self.get_file(unite=unite,fic_origine=self.parent.nom)
+         units={}
+         if f is not None:
+            self.fichier_ini = f
+            self.fichier_text=text
+         self.recorded_units=units
+         if self.fichier_ini 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")
+      else:
+         # Meme unite existante
+         f,text,units=self.parent.recorded_units[unite]
          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
+         self.fichier_text=text
+         self.recorded_units=units
 
-         if self.fichier_err is not None: raise Exception(self.fichier_err)
+      if self.fichier_ini is None:
+         # Le fichier n'est pas défini
+         self.fichier_err="Le fichier associé n'est pas défini"
+         self.parent.change_unit(unite,self,self.fichier_unite)
+         self.g_context={}
+         self.contexte_fichier_init={}
+         self.parent.reset_context()
+         self.reevalue_sd_jdc()
+         return
 
-         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
+      try:
+        self.make_contexte_include(self.fichier_ini,self.fichier_text)
+        # Les 3 attributs fichier_ini fichier_text recorded_units doivent etre corrects
+        # avant d'appeler change_unit
+        self.parent.change_unit(unite,self,self.fichier_unite)
+      except:
+        # Erreurs lors de l'evaluation de text dans un JDC auxiliaire
+        l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
+        # On conserve la memoire du nouveau fichier
+        # mais on n'utilise pas les concepts crees par ce fichier
+        # on met l'etape en erreur : fichier_err=string.join(l)
+        self.fichier_err=string.join(l)
+        self.parent.change_unit(unite,self,self.fichier_unite)
+        self.g_context={}
+        self.contexte_fichier_init={}
+
+      # Le contexte du parent doit etre reinitialise car les concepts 
+      # produits ont changé
+      self.parent.reset_context()
+      # Si des concepts ont disparu lors du changement de fichier, on 
+      # demande leur suppression
+      self.reevalue_sd_jdc()
 
+  def record_unite(self):
+      if self.nom == "POURSUITE":
+         self.parent.record_unit(None,self)
       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)
+         if hasattr(self,'fichier_unite') : 
+            self.parent.record_unit(self.fichier_unite,self)
 
+  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.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
+
+#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.jdc :
+         f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
+      else:
+         f,text=None,None
+      self.recorded_units=units
+      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
@@ -397,30 +404,32 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
 
       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)
+         f,text=self.get_file_memo(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
+         self.fichier_unite=unite
+         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)
+         if f is None:
+             self.fichier_err="Le fichier INCLUDE n est pas defini"
+             self.parent.record_unit(unite,self)
+             raise Exception(self.fichier_err)
 
          try:
            self.make_contexte_include(self.fichier_ini ,self.fichier_text)
+           self.parent.record_unit(unite,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 inclus",
                                             message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
                                            )
+           self.parent.record_unit(unite,self)
            self.g_context={}
-           self.etapes=[]
            self.fichier_err = string.join(l)
            self.contexte_fichier_init={}
            raise
@@ -428,11 +437,12 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
       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()
+         self.update_fichier_init(unite)
+         self.fichier_unite=unite
          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
@@ -443,6 +453,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
     # 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_unite =fichier
     self.fichier_text=text
     self.fichier_err=None 
     self.contexte_fichier_init={}
@@ -451,15 +462,16 @@ class MACRO_ETAPE(I_ETAPE.ETAPE):
     self.JdC_aux=Extensions.jdc_include.JdC_include
     try:
        self.make_contexte_include(self.fichier_ini ,self.fichier_text)
+       self.parent.record_unit(self.fichier_unite,self)
     except:
        l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
-       self.g_context={}
-       self.etapes=[]
        self.fichier_err = string.join(l)
+       self.parent.record_unit(self.fichier_unite,self)
+       self.g_context={}
        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
@@ -471,3 +483,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)
+