Salome HOME
*** empty log message ***
[tools/eficas.git] / Ihm / I_MACRO_ETAPE.py
index be318d25fbf2c096767eb7c6ee8f483e9ab13758..357fc5b783db4caf605f10980c99d792afe3fc83 100644 (file)
+# -*- coding: utf-8 -*-
+#            CONFIGURATION MANAGEMENT OF EDF VERSION
+# ======================================================================
+# COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
+# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
+# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
+# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
+# (AT YOUR OPTION) ANY LATER VERSION.
+#
+# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
+# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
+# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
+# GENERAL PUBLIC LICENSE FOR MORE DETAILS.
+#
+# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
+# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
+#    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
+#
+#
+# ======================================================================
 """
 """
 # Modules Python
+import sys
 import traceback,types,string
 
 # Modules Eficas
 import I_ETAPE
+import I_ENTITE
+import I_OBJECT
+import Noyau
 from Noyau.N_ASSD import ASSD
+from Noyau import N__F
+import convert
+from Extensions import param2
+
+# import rajoutés suite à l'ajout de Build_sd --> à résorber
+import Noyau, Validation.V_MACRO_ETAPE
+from Noyau import N_Exception
+from Noyau.N_Exception import AsException
+import Accas # attention aux imports circulaires
+# fin import à résorber
 
 class MACRO_ETAPE(I_ETAPE.ETAPE):
 
   def __init__(self):
-      I_ETAPE.ETAPE.__init__(self)
+      self.typret=None
+      #indique si le jeu de commande inclus a pu etre analysé par convert
+      #pour etre editable (0=NON, 1=OUI)
+      self.text_converted=1
+      self.text_error=""
+      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:
-      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
+         Interprète text comme un texte de jdc et retourne le contexte final.
+
+         Le contexte final est 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
     """
+    #print "get_contexte_jdc",self,self.nom
+    # On recupere l'etape courante
+    step=CONTEXT.get_current_step()
     try:
-       # on essaie de créer un objet JDC...
-       context_ini = self.parent.get_contexte_avant(self)
+       # on essaie de créer un objet JDC auxiliaire avec un contexte initial
+       # Attention get_contexte_avant retourne un dictionnaire qui contient
+       # le contexte courant. Ce dictionnaire est reactualise regulierement.
+       # Si on veut garder l'etat du contexte fige, il faut en faire une copie.
+       context_ini = self.parent.get_contexte_avant(self).copy()
+       #print "get_contexte_jdc",context_ini.keys()
 
+       # 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
+       # 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()
+
+       # on supprime l'ancien jdc_aux s'il existe
+       if hasattr(self,'jdc_aux') and self.jdc_aux:
+          self.jdc_aux.supprime_aux()
+
+       if fichier is None:fichier="SansNom"
+
+       # Il faut convertir le texte inclus en fonction du format
+       # sauf les INCLUDE_MATERIAU
+       self.text_converted=0
+       self.text_error=""
+       if self.nom != "INCLUDE_MATERIAU":
+          if self.parent.appli.ihm == "QT" :
+              format=self.parent.appli.appliEficas.format_fichier
+          else :
+              format=self.jdc.appli.format_fichier.get()
+          if convert.plugins.has_key(format):
+              # Le convertisseur existe on l'utilise
+              p=convert.plugins[format]()
+              p.text=text
+              text=p.convert('exec',self.jdc.appli)
+              #Si le fichier ne peut pas etre converti, le cr n'est pas vide
+              #et le texte est retourné tel que
+              if not p.cr.estvide(): 
+                  self.text_converted=0
+                  self.text_error=str(p.cr)
+              else:
+                  self.text_converted=1
+
+
+       j=self.JdC_aux( procedure=text, nom=fichier,
+                                appli=self.jdc.appli,
+                                cata=self.jdc.cata,
+                                cata_ord_dico=self.jdc.cata_ordonne_dico,
+                                context_ini = context_ini,
+                                jdc_pere=self.jdc,etape_include=self,
+                                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
+       self.jdc_aux=j
     except:
        traceback.print_exc()
+       # On retablit l'etape courante step
+       CONTEXT.unset_current_step()
+       CONTEXT.set_current_step(step)
        return None
-    CONTEXT.set_current_step(self)
+
     if not j.cr.estvide():
-        raise Exception("Impossible de relire le fichier\n"+str(j.cr))
-
-    #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))
-    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)
-    self.etapes=j.etapes
-    return j_context
+       # Erreurs dans l'INCLUDE. On garde la memoire du fichier 
+       # mais on n'insere pas les concepts
+       # On retablit l'etape courante step
+       #print j.cr
+       CONTEXT.unset_current_step()
+       CONTEXT.set_current_step(step)
+       raise Exception("Impossible de relire le fichier\n"+str(j.cr))
 
-  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)
+    if not j.isvalid():
+       # L'INCLUDE n'est pas valide.
+       # on produit un rapport d'erreurs
+       cr=j.report()
+       #print cr
+       # On retablit l'etape courante step
+       CONTEXT.unset_current_step()
+       CONTEXT.set_current_step(step)
+       raise Exception("Le fichier include contient des erreurs\n"+str(cr))
+
+    # Si aucune erreur rencontrée
+    # On recupere le contexte de l'include verifie
+    try:
+       j_context=j.get_verif_contexte()
+       #print j_context.keys()
+       #print j.g_context.keys()
+    except:
+       # On retablit l'etape courante step
+       CONTEXT.unset_current_step()
+       CONTEXT.set_current_step(step)
+       raise
+
+    # Si on est arrivé ici, le texte du fichier inclus (INCLUDE, POURSUITE, ...)
+    # est valide et insérable dans le JDC
+
+    # 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
+    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
+
+    #Ce traitement n'est réalisé que dans les cas suivants:
+    #     - si convert n'a pas pu convertir le jeu de commandes
+    #     - et ce n'est pas un INCLUDE_MATERIAU
+    #On collecte les variables Python qui ne sont pas dans le contexte initial
+    #et dans le contexte validé et on en fait un pseudo-parametre (Variable)
+    if self.text_converted == 0 and self.nom != "INCLUDE_MATERIAU":
+        for k,v in j.g_context.items():
+            if k in context_ini:continue
+            if k in j_context:continue
+            if isinstance(v,ASSD):continue
+            if isinstance(v,I_ENTITE.ENTITE):continue
+            if isinstance(v,I_OBJECT.OBJECT):continue
+            if callable(v):continue
+            self.g_context[k]=param2.Variable(k,v)
+
+    # On recupere le contexte courant
+    self.current_context=j.current_context
+    self.index_etape_courante=j.index_etape_courante
+    self.jdc_aux=j
+
+    # On retablit l'etape courante step
+    CONTEXT.unset_current_step()
+    CONTEXT.set_current_step(step)
+
+    return j_context
 
   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)
+     #print "reevalue_sd_jdc"
+     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 verifier que les concepts produits par la 
+          commande ne sont pas incompatibles avec le contexte fourni (d).
+          Si c'est le cas, le concept produit doit etre supprime
+          Si la macro a elle meme des etapes, elle doit propager
+          le traitement (voir methode control_jdc_context_apres de I_JDC)
+      """
+      #print "I_MACRO_ETAPE.control_sdprods",d.keys(),self.nom,self.sd and self.sd.nom
+      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.init_modif()
+              sd=self.sd
+              self.sd=self.reuse=self.sdnom=None
+              self.parent.delete_concept_after_etape(self,sd)
+              self.fin_modif()
+
+      # On verifie les concepts a droite du signe =
+      self.init_modif()
+      sdprods=self.sdprods[:]
+      self.sdprods=[]
+      for co in sdprods:
+        if d.has_key(co.nom) and co is not d[co.nom] :
+           #nettoie les mots cles de l'étape qui ont comme valeur co
+           self.delete_concept(co)
+           #supprime les references a co dans les etapes suivantes
+           self.parent.delete_concept_after_etape(self,co)
+        else:
+           self.sdprods.append(co)
+      self.fin_modif()
+       
+      for e in self.etapes:
+          e.control_sdprods(d)
+          e.update_context(d)
+
+  def supprime_sdprod(self,sd):
+      """
+         Supprime le concept produit sd s'il est produit par l'etape
+      """
+      if sd in self.sdprods:
+         self.init_modif()
+         self.parent.del_sdprod(sd)
+         self.sdprods.remove(sd)
+         self.fin_modif()
+         self.parent.delete_concept(sd)
+         return
+
+      if sd is not self.sd :return
+      if self.sd is not None :
+         self.init_modif()
+         self.parent.del_sdprod(sd)
+         self.sd=None
+         self.fin_modif()
+         self.parent.delete_concept(sd)
+
   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
+          Fonction: Lors de la destruction de la macro-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() :
+      #print "supprime_sdprods"
+      if self.reuse is not self.sd :
          # l'étape n'est pas réentrante
          # le concept retourné par l'étape est à supprimer car il était
          # créé par l'étape
@@ -140,9 +342,701 @@ 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={}
+
+  def close(self):
+      #print "close",self
+      if hasattr(self,"jdc_aux") and self.jdc_aux:
+         # La macro a un jdc auxiliaire inclus. On demande sa fermeture
+         self.jdc_aux.close()
+
+  def reset_context(self):
+      if hasattr(self,"jdc_aux") and self.jdc_aux:
+         # La macro a un jdc auxiliaire inclus. On demande la reinitialisation du contexte
+         self.jdc_aux.reset_context()
+
+  def update_concept(self,sd):
+      I_ETAPE.ETAPE.update_concept(self,sd)
+      for etape in self.etapes:
+          etape.update_concept(sd)
+
+  def delete_concept(self,sd):
+      """
+          Fonction : 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
+      """
+      #print "delete_concept",sd
+      I_ETAPE.ETAPE.delete_concept(self,sd)
+      for etape in self.etapes:
+         etape.delete_concept(sd)
+
+  def replace_concept(self,old_sd,sd):
+      """
+          Fonction : Mettre a jour les mots cles de l etape et le concept produit si reuse 
+          suite au remplacement  du concept old_sd par sd
+      """
+      #print "replace_concept",old_sd,sd
+      I_ETAPE.ETAPE.replace_concept(self,old_sd,sd)
+      for etape in self.etapes:
+         etape.replace_concept(old_sd,sd)
          
+  def change_fichier_init(self,new_fic,text):
+    """
+       Tente de changer le fichier include. Le precedent include est conservé
+       dans old_xxx
+    """
+    #print "change_fichier_init",new_fic
+    if not hasattr(self,'fichier_ini'):
+       self.fichier_ini=None
+       self.fichier_text=None
+       self.fichier_err="Le fichier n'est pas defini"
+       self.contexte_fichier_init={}
+       self.recorded_units={}
+       self.jdc_aux=None
+       self.fichier_unite="PasDefini"
+       import Extensions.jdc_include
+       self.JdC_aux=Extensions.jdc_include.JdC_include
+
+    self.old_fic = self.fichier_ini
+    self.old_text = self.fichier_text
+    self.old_err = self.fichier_err
+    self.old_context=self.contexte_fichier_init
+    self.old_units=self.recorded_units
+    self.old_etapes=self.etapes
+    self.old_jdc_aux=self.jdc_aux
+
+    self.fichier_ini = new_fic
+    self.fichier_text=text
+
+    try:
+       self.make_contexte_include(new_fic,text)
+    except:
+       l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
+       self.fichier_err=string.join(l)
+       raise
+
+    # L'evaluation de text dans un JDC auxiliaire s'est bien passé
+    # on peut poursuivre le traitement
+    self.init_modif()
+    self.state="undetermined"
+    self.fichier_err=None
+    # On enregistre la modification de fichier
+    self.record_unite()
+    # 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.old_contexte_fichier_init=self.old_context
+    self.reevalue_sd_jdc()
+
+    self.fin_modif()
+    if self.old_jdc_aux:
+       self.old_jdc_aux.close()
+
+  def restore_fichier_init(self):
+    """
+       Restaure le fichier init enregistre dans old_xxx
+    """
+    self.fichier_ini=self.old_fic
+    self.fichier_text=self.old_text
+    self.fichier_err=self.old_err
+    self.contexte_fichier_init=self.old_context
+    self.recorded_units=self.old_units
+    self.etapes=self.old_etapes
+    self.jdc_aux=self.old_jdc_aux
+
+  def force_fichier_init(self):
+    """
+       Force le remplacement du fichier init meme si le remplacant est en erreur
+    """
+    # Reinitialisation complete du compte-rendu d'erreurs
+    self.jdc_aux.cr=self.jdc_aux.CR()
+    # 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
+    j_context=self.jdc_aux.get_contexte_avant(None)
+    self.g_context.clear()
+    context_ini=self.jdc_aux.context_ini
+    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 recupere le contexte courant
+    self.current_context=self.jdc_aux.current_context
+    self.index_etape_courante=self.jdc_aux.index_etape_courante
+    self.contexte_fichier_init = j_context
+    self.fichier_err = None
+
+    # On enregistre la modification de fichier
+    self.init_modif()
+    self.state="undetermined"
+    self.record_unite()
+    # Le contexte du parent doit etre reinitialise car les concepts produits ont changé
+    self.parent.reset_context()
+
+    # On remplace les anciens concepts par les nouveaux (y compris ajouts 
+    # et suppression) et on propage les modifications aux etapes precedentes et suivantes
+    # reevalue_sd_jdc construit la liste des differences entre les contextes contexte_fichier_init
+    # et old_contexte_fichier_init et effectue les destructions et remplacements de concept
+    # necessaires
+    self.old_contexte_fichier_init=self.old_context
+    self.reevalue_sd_jdc()
+    self.fin_modif()
+    if self.old_jdc_aux:
+       self.old_jdc_aux.close()
+
+    self.jdc_aux.force_contexte(self.g_context)
+
+  def build_include(self,fichier,text):
+    import Extensions.jdc_include
+    self.JdC_aux=Extensions.jdc_include.JdC_include
+    # un include partage la table des unites avec son parent (jdc)
+    self.recorded_units=self.parent.recorded_units
+    self.build_jdcaux(fichier,text)
+
+  def build_poursuite(self,fichier,text):
+    import Extensions.jdc_include
+    self.JdC_aux=Extensions.jdc_include.JdC_poursuite
+    # une poursuite a sa propre table d'unites
+    self.recorded_units={}
+    self.build_jdcaux(fichier,text)
+
+  def build_jdcaux(self,fichier,text):
+    """
+         Cree un jdc auxiliaire initialise avec text. 
+         Initialise le nom du fichier associé avec fichier
+         N'enregistre pas d'association unite <-> fichier
+    """
+    self.fichier_ini = fichier
+    self.fichier_text= text
+    self.fichier_unite=None
+    self.fichier_err = None
+    try:
+       contexte = self.get_contexte_jdc(fichier,text)
+       if contexte is None :
+          # Impossible de construire le jdc auxiliaire (sortie par None)
+          # On simule une sortie par exception
+          raise Exception("Impossible de construire le jeu de commandes correspondant au fichier")
+       else:
+          # La construction du jdc auxiliaire est allée au bout
+          self.contexte_fichier_init = contexte
+       self.init_modif()
+       self.fin_modif()
+    except:
+       # Impossible de construire le jdc auxiliaire (sortie par exception)
+       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.jdc_aux=None
+       self.fichier_err = string.join(l)
+       self.contexte_fichier_init={}
+       self.init_modif()
+       self.fin_modif()
+       raise
+
+  def make_contexte_include(self,fichier,text):
+    """
+        Cette méthode sert à créer un contexte en interprétant un texte source Python.
+    """
+    #print "make_contexte_include",fichier
+    # 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_OBSOLETE(self):
+      """Recalcule les concepts produits par le fichier enregistre"""
+      #print "reevalue_fichier_init"
+      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.g_context={}
+         self.etapes=[]
+         self.jdc_aux=None
+         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 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
+         L'include a été initialisé précédemment. Le jdc auxiliaire existe.
+      """
+      #print "update_fichier_init",unite,self.fichier_unite 
+      self.old_contexte_fichier_init=self.contexte_fichier_init
+      old_fichier_ini=self.fichier_ini
+      if not hasattr(self,"jdc_aux"):self.jdc_aux=None
+      old_jdc_aux=self.jdc_aux
+
+      #print "update_fichier_init",self,self.parent,self.parent.recorded_units
+
+      if self.fichier_unite is None:
+         # L'unité n'était pas définie précédemment. On ne change que l'unite
+         #print "update_fichier_init","pas de changement dans include"
+         self.fichier_unite=unite
+         return
+      elif unite == self.fichier_unite :
+         # L'unité n'a pas changé
+         #print "update_fichier_init","pas de changement dans include 3"
+         return
+      elif unite != self.fichier_unite :
+         # L'unité était définie précédemment. On remplace l'include 
+         #
+         f,text=self.get_file_memo(unite=unite,fic_origine=self.parent.nom)
+         if f is None:
+            # Le fichier associé n'a pas pu etre defini
+            # on change l'unite associée mais pas l'include
+            #print "update_fichier_init","pas de changement dans include 2"
+            self.fichier_unite=unite
+            return
+         else:
+            self.fichier_ini = f
+            self.fichier_text=text
+            self.fichier_unite=unite
+         #print "update_fichier_init",self.recorded_units
+
+      #print "update_fichier_init",self.fichier_ini,self.fichier_text,self.fichier_unite
+
+      if old_fichier_ini == self.fichier_ini:
+         # Le fichier inclus n'a pas changé. On ne recrée pas le contexte
+         # mais on enregistre le changement d'association unite <-> fichier
+         #print "update_fichier_init.fichier inchange",self.jdc_aux.context_ini
+         self.parent.record_unit(unite,self)
+         return
+
+      try:
+        self.fichier_err=None
+        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
+      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.g_context={}
+        self.etapes=[]
+        self.jdc_aux=None
+        self.contexte_fichier_init={}
+
+      if old_jdc_aux:
+         old_jdc_aux.close()
+      self.parent.record_unit(unite,self)
+      # 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()
+      #print "update_fichier_init",self.jdc_aux.context_ini.keys()
+
+  def record_unite(self):
+      #print "record_unite",self.nom
+      if self.nom == "POURSUITE":
+         self.parent.record_unit(None,self)
+      else:
+         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
+      """
+      #print "get_file_memo",unite,fic_origine,self,self.parent
+      #print self.parent.recorded_units
+      if unite is None:
+         # On est dans le cas d'une poursuite. On ne reutilise aucune unite de parent
+         units={}
+      else:
+         # On est dans le cas d'un include. On reutilise toutes les unites de parent
+         units=self.parent.recorded_units
+
+      if self.parent.recorded_units.has_key(unite):
+         f,text,units=self.parent.recorded_units[unite]
+      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 update_context(self,d):
+      """
+         Met à jour le contexte contenu dans le dictionnaire d
+         Une MACRO_ETAPE peut ajouter plusieurs concepts dans le contexte
+         Une fonction enregistree dans op_init peut egalement modifier le contexte
+      """
+      #print "update_context",self,self.nom,d.keys()
+      if hasattr(self,"jdc_aux") and self.jdc_aux:
+            #ATTENTION: update_context NE DOIT PAS appeler reset_context
+            # car il appelle directement ou indirectement update_context
+            # equivalent a reset_context. Evite les recursions
+            self.jdc_aux.context_ini=d.copy()
+            self.jdc_aux.current_context={}
+            self.jdc_aux.index_etape_courante=0
+            #ATTENTION: il ne faut pas utiliser self.jdc_aux.get_contexte_avant
+            #car cet appel conduit a des remontées multiples incohérentes dans le
+            # ou les parents. 
+            #get_context_avant appelle update_context qui NE DOIT PAS appeler get_contexte_avant
+            #On n'a besoin que d'un update local connaissant
+            # le contexte amont : d qui sert a reinitialiser self.context_ini
+            for e in self.etapes:
+                e.update_context(d)
+            return
+
+      if type(self.definition.op_init) == types.FunctionType:
+        apply(self.definition.op_init,(self,d))
+      if self.sd != None:d[self.sd.nom]=self.sd
+      for co in self.sdprods:
+        d[co.nom]=co
+      #print "update_context.fin",d.keys()
+
+#ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
+  def copy(self):
+      etape=Noyau.N_MACRO_ETAPE.MACRO_ETAPE.copy(self)
+      if hasattr(etape,"etapes") :etape.etapes=[]
+      if hasattr(etape,"jdc_aux") : 
+         etape.jdc_aux=None
+         del etape.fichier_ini
+      return etape
+
+  def supprime(self):
+      #print "supprime",self
+      if hasattr(self,"jdc_aux") and self.jdc_aux:
+         self.jdc_aux.supprime_aux()
+         self.jdc_aux=None
+      Noyau.N_MACRO_ETAPE.MACRO_ETAPE.supprime(self)
+  #    self.contexte_fichier_init={}
+  #    self.old_contexte_fichier_init={}
+  #    self.g_context={}
+  #    self.current_context={}
+  #    self.etapes=[]
+  #    self.mc_liste=[]
+
+#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
+      """
+      if self.jdc :
+         f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
+      else:
+         f,text=None,None
+      return f,text
+
+
+  def make_include2(self,fichier=None):
+      # gestion de l unicite SVP
+      unite=999
+      if hasattr(self,'fichier_ini') : return
+      #print "je passe le if"
+      if fichier == None :
+         fichier=str(self.jdc.appli.get_file_variable())
+         #print fichier
+         if fichier  == str("") : 
+           self.fichier_ini="badfile"
+           self.fichier_text=""
+          self.fichier_err="Le fichier INCLUDE n est pas defini"
+           self.parent.record_unit(999,self)
+           try :
+              MCFils=self.get_child('FileName')
+              MCFils.set_valeur(None)
+           except :
+              pass
+           raise Exception(self.fichier_err)
+
+         # On memorise le fichier retourne
+      self.fichier_ini  = fichier
+      self.fichier_text = ""
+      self.contexte_fichier_init={}
+      self.fichier_unite=999
+      self.fichier_err=None
+      try :
+         from openturns import WrapperFile
+         monWrapper=WrapperFile(fichier)
+         data=monWrapper.getWrapperData()
+         maVariableListe=data.getVariableList()
+         nbVariables=maVariableListe.getSize()
+         for i in range(nbVariables) :
+             nom=maVariableListe[i].id_
+             type=maVariableListe[i].type_
+             if type :
+               ligneTexte="%s=DETERMINISTICVARIABLE(N='%s',T='in',R=%d);\n" % (nom, nom, i)
+             else :
+               ligneTexte="%s=DETERMINISTICVARIABLE(N='%s',T='out',R=%d);\n" % (nom, nom, i)
+             self.fichier_text = self.fichier_text + ligneTexte
+      except:
+         self.make_incl2_except()
+         raise
+
+      try:
+         import Extensions.jdc_include
+      except:
+         traceback.print_exc()
+         self.make_incl2_except()
+         raise
+      self.JdC_aux=Extensions.jdc_include.JdC_include
+      
+      try:
+         self.make_contexte_include(self.fichier_ini ,self.fichier_text)
+         self.parent.record_unit(unite,self)
+         try :
+            MCFils=self.get_child('FileName')
+            MCFils.set_valeur(fichier)
+         except :
+            pass
+      except:
+         self.make_incl2_except()
+         raise
+
+  def make_incl2_except(self):
+         #print "make_incl2_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="Le contenu de ce fichier ne sera pas pris en compte\n"+string.join(l)
+                                           )
+         self.parent.record_unit(unite,self)
+         self.g_context={}
+         self.etapes=[]
+         self.jdc_aux=None
+         self.fichier_err = string.join(l)
+         self.contexte_fichier_init={}
+         try :
+            MCFils=self.get_child('FileName')
+            MCFils.set_valeur(None)
+         except :
+            pass
+
+
+#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
+          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 ???)
+      """
+      #print "make_include",unite
+      # 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
+      # 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_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={}
+         self.fichier_unite=unite
+         self.fichier_err=None
+         try:
+           import Extensions.jdc_include
+         except:
+           traceback.print_exc()
+           raise
+         self.JdC_aux=Extensions.jdc_include.JdC_include
+
+         #print "make_include",self.fichier_ini,self.fichier_text 
+         if f is None and not text:
+             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="Le contenu de ce fichier ne sera pas pris en compte\n"+string.join(l)
+                                           )
+           self.parent.record_unit(unite,self)
+           self.g_context={}
+           self.etapes=[]
+           self.jdc_aux=None
+           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(unite)
+         self.fichier_unite=unite
+         if self.fichier_err is not None: raise Exception(self.fichier_err)
+        
+
+#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
+        en interprétant un texte source Python
+        Elle est appelee par la fonction sd_prod d'INCLUDE_MATERIAU
+    """
+    #print "make_contexte",fichier
+    # 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
+    if not hasattr(self,'fichier_ini') or self.fichier_ini != fichier or self.fichier_mater != self.nom_mater: 
+       # le fichier est nouveau ou change
+       self.fichier_ini =fichier
+       self.fichier_unite =fichier
+       self.fichier_mater=self.nom_mater
+       self.fichier_text=text
+       self.fichier_err=None 
+       self.contexte_fichier_init={}
+       # On specifie la classe a utiliser pour le JDC auxiliaire
+       try:
+         import Extensions.jdc_include
+         self.JdC_aux=Extensions.jdc_include.JdC_include
+       except:
+         raise
+       try:
+          self.make_contexte_include(self.fichier_ini ,self.fichier_text)
+          if not self.g_context.has_key(self.nom_mater):
+             #Pour permettre de lire un jeu de commandes avec des INCLUDE_MATERIAU errones
+             self.g_context[self.nom_mater]=None
+             if self.parent: self.parent.g_context[self.nom_mater]=None
+       except:
+          l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
+          self.fichier_err = string.join(l)
+          self.g_context={}
+          #Pour permettre de lire un jeu de commandes avec des INCLUDE_MATERIAU errones
+          if self.parent:
+              self.parent.g_context[self.nom_mater]=None
+          self.g_context[self.nom_mater]=None
+          #-------------
+          self.etapes=[]
+          self.jdc_aux=None
+          self.contexte_fichier_init={}
+          raise
+    else:
+       # le fichier est le meme on ne le reevalue pas
+       # 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 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
+     # 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
+
+#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)
+      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
+      """
+      #print "make_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
+         try:
+           import Extensions.jdc_include
+         except:
+           traceback.print_exc()
+           raise
+         self.JdC_aux=Extensions.jdc_include.JdC_poursuite
+         self.contexte_fichier_init={}
+         #print "make_poursuite",self.fichier_ini,self.fichier_text
+
+         if f is None:
+             self.fichier_err="Le fichier POURSUITE n'est pas defini"
+             self.jdc_aux=None
+             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.etapes=[]
+           self.jdc_aux=None
+           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)