Salome HOME
Modif V6_4_°
[tools/eficas.git] / Ihm / I_MACRO_ETAPE.py
1 # -*- coding: iso-8859-1 -*-
2 #            CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
18 #
19 #
20 # ======================================================================
21 """
22 """
23 # Modules Python
24 import sys
25 import traceback,types,string
26
27 # Modules Eficas
28 import I_ETAPE
29 import I_ENTITE
30 import I_OBJECT
31 import Noyau
32 from Noyau.N_ASSD import ASSD
33 from Noyau import N__F
34 import convert
35 from Extensions import param2
36
37 # import rajoutés suite à l'ajout de Build_sd --> à résorber
38 import Noyau, Validation.V_MACRO_ETAPE
39 from Noyau import N_Exception
40 from Noyau.N_Exception import AsException
41 import Accas # attention aux imports circulaires
42 # fin import à résorber
43
44 class MACRO_ETAPE(I_ETAPE.ETAPE):
45
46   def __init__(self):
47       self.typret=None
48       #indique si le jeu de commande inclus a pu etre analysé par convert
49       #pour etre editable (0=NON, 1=OUI)
50       self.text_converted=1
51       self.text_error=""
52       self.recorded_units={}
53
54   def get_sdprods(self,nom_sd):
55     """ 
56          Fonction : retourne le concept produit par l etape de nom nom_sd
57          s il existe sinon None
58     """
59     if self.sd and self.sd.nom == nom_sd :return self.sd
60     for co in self.sdprods:
61       if co.nom == nom_sd:return co
62     if type(self.definition.op_init) == types.FunctionType:
63       d={}
64       apply(self.definition.op_init,(self,d))
65       return d.get(nom_sd,None)
66     return None
67
68   def get_contexte_jdc(self,fichier,text):
69     """ 
70          Interprète text comme un texte de jdc et retourne le contexte final.
71
72          Le contexte final est le dictionnaire des sd disponibles à la dernière étape.
73          Si text n'est pas un texte de jdc valide, retourne None
74          ou leve une exception
75          --> utilisée par ops.POURSUITE et INCLUDE
76     """
77     #print "get_contexte_jdc",self,self.nom
78     # On recupere l'etape courante
79     step=CONTEXT.get_current_step()
80     try:
81        # on essaie de créer un objet JDC auxiliaire avec un contexte initial
82        # Attention get_contexte_avant retourne un dictionnaire qui contient
83        # le contexte courant. Ce dictionnaire est reactualise regulierement.
84        # Si on veut garder l'etat du contexte fige, il faut en faire une copie.
85        context_ini = self.parent.get_contexte_avant(self).copy()
86        #print "get_contexte_jdc",context_ini.keys()
87
88        # Indispensable avant de creer un nouveau JDC
89        CONTEXT.unset_current_step()
90        args=self.jdc.args
91        prefix_include=None
92        if hasattr(self,'prefix'):
93           prefix_include=self.prefix
94        # ATTENTION : le dictionnaire recorded_units sert à memoriser les unites des 
95        # fichiers inclus. Il est preferable de garder le meme dictionnaire pendant
96        # tout le traitement et de ne pas le reinitialiser brutalement (utiliser 
97        # clear plutot) si on ne veut pas perdre la memoire des unites.
98        # En principe si la memorisation est faite au bon moment il n'est pas necessaire
99        # de prendre cette precaution mais ce n'est pas vrai partout.
100        old_recorded_units=self.recorded_units.copy()
101
102        # on supprime l'ancien jdc_aux s'il existe
103        if hasattr(self,'jdc_aux') and self.jdc_aux:
104           self.jdc_aux.supprime_aux()
105
106        if fichier is None:fichier="SansNom"
107
108        # Il faut convertir le texte inclus en fonction du format
109        # sauf les INCLUDE_MATERIAU
110        self.text_converted=0
111        self.text_error=""
112        if self.nom != "INCLUDE_MATERIAU":
113           if self.parent.appli.ihm == "QT" :
114               format=self.parent.appli.appliEficas.format_fichier
115           else :
116               format=self.jdc.appli.format_fichier.get()
117           if convert.plugins.has_key(format):
118               # Le convertisseur existe on l'utilise
119               p=convert.plugins[format]()
120               p.text=text
121               text=p.convert('exec',self.jdc.appli)
122               #Si le fichier ne peut pas etre converti, le cr n'est pas vide
123               #et le texte est retourné tel que
124               if not p.cr.estvide(): 
125                   self.text_converted=0
126                   self.text_error=str(p.cr)
127               else:
128                   self.text_converted=1
129
130
131        j=self.JdC_aux( procedure=text, nom=fichier,
132                                 appli=self.jdc.appli,
133                                 cata=self.jdc.cata,
134                                 cata_ord_dico=self.jdc.cata_ordonne_dico,
135                                 context_ini = context_ini,
136                                 jdc_pere=self.jdc,etape_include=self,
137                                 prefix_include=prefix_include,
138                                 recorded_units=self.recorded_units,
139                                 old_recorded_units=old_recorded_units,**args)
140
141        j.analyse()
142        # On récupère les étapes internes (pour validation)
143        self.etapes=j.etapes
144        self.jdc_aux=j
145     except:
146        traceback.print_exc()
147        # On retablit l'etape courante step
148        CONTEXT.unset_current_step()
149        CONTEXT.set_current_step(step)
150        return None
151
152     if not j.cr.estvide():
153        # Erreurs dans l'INCLUDE. On garde la memoire du fichier 
154        # mais on n'insere pas les concepts
155        # On retablit l'etape courante step
156        #print j.cr
157        CONTEXT.unset_current_step()
158        CONTEXT.set_current_step(step)
159        raise Exception("Impossible de relire le fichier\n"+str(j.cr))
160
161     if not j.isvalid():
162        # L'INCLUDE n'est pas valide.
163        # on produit un rapport d'erreurs
164        cr=j.report()
165        #print cr
166        # On retablit l'etape courante step
167        CONTEXT.unset_current_step()
168        CONTEXT.set_current_step(step)
169        raise Exception("Le fichier include contient des erreurs\n"+str(cr))
170
171     # Si aucune erreur rencontrée
172     # On recupere le contexte de l'include verifie
173     try:
174        j_context=j.get_verif_contexte()
175        #print j_context.keys()
176        #print j.g_context.keys()
177     except:
178        # On retablit l'etape courante step
179        CONTEXT.unset_current_step()
180        CONTEXT.set_current_step(step)
181        raise
182
183     # Si on est arrivé ici, le texte du fichier inclus (INCLUDE, POURSUITE, ...)
184     # est valide et insérable dans le JDC
185
186     # On remplit le dictionnaire des concepts produits inclus
187     # en retirant les concepts présents dans le  contexte initial
188     # On ajoute egalement le concept produit dans le sds_dict du parent
189     # sans verification car on est sur (verification integrée) que 
190     # le nommage est possible
191     self.g_context.clear()
192     for k,v in j_context.items():
193        if not context_ini.has_key(k) or context_ini[k] != v:
194            self.g_context[k]=v
195            self.parent.sds_dict[k]=v
196
197     #Ce traitement n'est réalisé que dans les cas suivants:
198     #     - si convert n'a pas pu convertir le jeu de commandes
199     #     - et ce n'est pas un INCLUDE_MATERIAU
200     #On collecte les variables Python qui ne sont pas dans le contexte initial
201     #et dans le contexte validé et on en fait un pseudo-parametre (Variable)
202     if self.text_converted == 0 and self.nom != "INCLUDE_MATERIAU":
203         for k,v in j.g_context.items():
204             if k in context_ini:continue
205             if k in j_context:continue
206             if isinstance(v,ASSD):continue
207             if isinstance(v,I_ENTITE.ENTITE):continue
208             if isinstance(v,I_OBJECT.OBJECT):continue
209             if callable(v):continue
210             self.g_context[k]=param2.Variable(k,v)
211
212     # On recupere le contexte courant
213     self.current_context=j.current_context
214     self.index_etape_courante=j.index_etape_courante
215     self.jdc_aux=j
216
217     # On retablit l'etape courante step
218     CONTEXT.unset_current_step()
219     CONTEXT.set_current_step(step)
220
221     return j_context
222
223   def reevalue_sd_jdc(self):
224      """
225          Avec la liste des SD qui ont été supprimées, propage la 
226          disparition de ces SD dans toutes les étapes et descendants
227      """
228      #print "reevalue_sd_jdc"
229      l_sd_supp,l_sd_repl = self.diff_contextes()
230      for sd in l_sd_supp:
231         self.parent.delete_concept_after_etape(self,sd)
232      for old_sd,sd in l_sd_repl:
233         self.parent.replace_concept_after_etape(self,old_sd,sd)
234
235   def diff_contextes(self):
236      """ 
237          Réalise la différence entre les 2 contextes 
238          old_contexte_fichier_init et contexte_fichier_init
239          cad retourne la liste des sd qui ont disparu ou ne derivent pas 
240          de la meme classe et des sd qui ont ete remplacees
241      """
242      if not hasattr(self,'old_contexte_fichier_init'):return [],[]
243      l_sd_suppressed = []
244      l_sd_replaced = []
245      for old_key in self.old_contexte_fichier_init.keys():
246        if not self.contexte_fichier_init.has_key(old_key):
247          if isinstance(self.old_contexte_fichier_init[old_key],ASSD):
248            l_sd_suppressed.append(self.old_contexte_fichier_init[old_key])
249        else:
250          if isinstance(self.old_contexte_fichier_init[old_key],ASSD):
251             # Un concept de meme nom existe
252             old_class=self.old_contexte_fichier_init[old_key].__class__
253             if not isinstance(self.contexte_fichier_init[old_key],old_class):
254                # S'il n'est pas d'une classe derivee, on le supprime
255                l_sd_suppressed.append(self.old_contexte_fichier_init[old_key])
256             else:
257                l_sd_replaced.append((self.old_contexte_fichier_init[old_key],self.contexte_fichier_init[old_key]))
258      return l_sd_suppressed,l_sd_replaced
259       
260   def control_sdprods(self,d):
261       """
262           Cette methode doit verifier que les concepts produits par la 
263           commande ne sont pas incompatibles avec le contexte fourni (d).
264           Si c'est le cas, le concept produit doit etre supprime
265           Si la macro a elle meme des etapes, elle doit propager
266           le traitement (voir methode control_jdc_context_apres de I_JDC)
267       """
268       #print "I_MACRO_ETAPE.control_sdprods",d.keys(),self.nom,self.sd and self.sd.nom
269       if self.sd:
270         if d.has_key(self.sd.nom):
271            # Le concept est deja defini
272            if self.reuse and self.reuse is d[self.sd.nom]:
273               # Le concept est reutilise : situation normale
274               pass
275            else:
276               # Redefinition du concept, on l'annule
277               #XXX on pourrait simplement annuler son nom pour conserver les objets
278               # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
279               self.init_modif()
280               sd=self.sd
281               self.sd=self.reuse=self.sdnom=None
282               self.parent.delete_concept_after_etape(self,sd)
283               self.fin_modif()
284
285       # On verifie les concepts a droite du signe =
286       self.init_modif()
287       sdprods=self.sdprods[:]
288       self.sdprods=[]
289       for co in sdprods:
290         if d.has_key(co.nom) and co is not d[co.nom] :
291            #nettoie les mots cles de l'étape qui ont comme valeur co
292            self.delete_concept(co)
293            #supprime les references a co dans les etapes suivantes
294            self.parent.delete_concept_after_etape(self,co)
295         else:
296            self.sdprods.append(co)
297       self.fin_modif()
298        
299       for e in self.etapes:
300           e.control_sdprods(d)
301           e.update_context(d)
302
303   def supprime_sdprod(self,sd):
304       """
305          Supprime le concept produit sd s'il est produit par l'etape
306       """
307       if sd in self.sdprods:
308          self.init_modif()
309          self.parent.del_sdprod(sd)
310          self.sdprods.remove(sd)
311          self.fin_modif()
312          self.parent.delete_concept(sd)
313          return
314
315       if sd is not self.sd :return
316       if self.sd is not None :
317          self.init_modif()
318          self.parent.del_sdprod(sd)
319          self.sd=None
320          self.fin_modif()
321          self.parent.delete_concept(sd)
322
323   def supprime_sdprods(self):
324       """
325           Fonction: Lors de la destruction de la macro-etape, detruit tous les concepts produits
326           Un opérateur n a qu un concept produit
327           Une procedure n'en a aucun
328           Une macro en a en général plus d'un
329       """
330       #print "supprime_sdprods"
331       if self.reuse is not self.sd :
332          # l'étape n'est pas réentrante
333          # le concept retourné par l'étape est à supprimer car il était
334          # créé par l'étape
335          if self.sd != None :
336             self.parent.del_sdprod(self.sd)
337             self.parent.delete_concept(self.sd)
338       # On détruit les concepts à droite du signe =
339       for co in self.sdprods:
340          self.parent.del_sdprod(co)
341          self.parent.delete_concept(co)
342       # Si la macro a des etapes et des concepts inclus, on les detruit
343       for nom_sd,co in self.g_context.items():
344          if not isinstance(co,ASSD):continue
345          self.parent.del_sdprod(co)
346          self.parent.delete_concept(co)
347       # On met g_context à blanc
348       self.g_context={}
349
350   def close(self):
351       #print "close",self
352       if hasattr(self,"jdc_aux") and self.jdc_aux:
353          # La macro a un jdc auxiliaire inclus. On demande sa fermeture
354          self.jdc_aux.close()
355
356   def reset_context(self):
357       if hasattr(self,"jdc_aux") and self.jdc_aux:
358          # La macro a un jdc auxiliaire inclus. On demande la reinitialisation du contexte
359          self.jdc_aux.reset_context()
360
361   def update_concept(self,sd):
362       I_ETAPE.ETAPE.update_concept(self,sd)
363       for etape in self.etapes:
364           etape.update_concept(sd)
365
366   def delete_concept(self,sd):
367       """
368           Fonction : Mettre a jour les mots cles de l etape et eventuellement
369           le concept produit si reuse suite à la disparition du concept sd
370           Seuls les mots cles simples MCSIMP font un traitement autre
371           que de transmettre aux fils
372       """
373       #print "delete_concept",sd
374       I_ETAPE.ETAPE.delete_concept(self,sd)
375       for etape in self.etapes:
376          etape.delete_concept(sd)
377
378   def replace_concept(self,old_sd,sd):
379       """
380           Fonction : Mettre a jour les mots cles de l etape et le concept produit si reuse 
381           suite au remplacement  du concept old_sd par sd
382       """
383       #print "replace_concept",old_sd,sd
384       I_ETAPE.ETAPE.replace_concept(self,old_sd,sd)
385       for etape in self.etapes:
386          etape.replace_concept(old_sd,sd)
387          
388   def change_fichier_init(self,new_fic,text):
389     """
390        Tente de changer le fichier include. Le precedent include est conservé
391        dans old_xxx
392     """
393     print "change_fichier_init",new_fic
394     if not hasattr(self,'fichier_ini'):
395        self.fichier_ini=None
396        self.fichier_text=None
397        self.fichier_err="Le fichier n'est pas defini"
398        self.contexte_fichier_init={}
399        self.recorded_units={}
400        self.jdc_aux=None
401        self.fichier_unite="PasDefini"
402        import Extensions.jdc_include
403        self.JdC_aux=Extensions.jdc_include.JdC_include
404
405     self.old_fic = self.fichier_ini
406     print self.old_fic
407     self.old_text = self.fichier_text
408     print self.old_text
409     self.old_err = self.fichier_err
410     self.old_context=self.contexte_fichier_init
411     print self.old_context
412     self.old_units=self.recorded_units
413     self.old_etapes=self.etapes
414     print self.old_etapes
415     self.old_jdc_aux=self.jdc_aux
416
417     self.fichier_ini = new_fic
418     self.fichier_text=text
419
420     try:
421        self.make_contexte_include(new_fic,text)
422     except:
423        l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
424        self.fichier_err=string.join(l)
425        raise
426
427     # L'evaluation de text dans un JDC auxiliaire s'est bien passé
428     # on peut poursuivre le traitement
429     self.init_modif()
430     self.state="undetermined"
431     self.fichier_err=None
432     # On enregistre la modification de fichier
433     self.record_unite()
434     # Le contexte du parent doit etre reinitialise car les concepts produits ont changé
435     self.parent.reset_context()
436
437     # Si des concepts ont disparu lors du changement de fichier, on demande leur suppression
438     self.old_contexte_fichier_init=self.old_context
439     self.reevalue_sd_jdc()
440
441     self.fin_modif()
442     if self.old_jdc_aux:
443        self.old_jdc_aux.close()
444
445   def restore_fichier_init(self):
446     """
447        Restaure le fichier init enregistre dans old_xxx
448     """
449     self.fichier_ini=self.old_fic
450     self.fichier_text=self.old_text
451     self.fichier_err=self.old_err
452     self.contexte_fichier_init=self.old_context
453     self.recorded_units=self.old_units
454     self.etapes=self.old_etapes
455     self.jdc_aux=self.old_jdc_aux
456
457   def force_fichier_init(self):
458     """
459        Force le remplacement du fichier init meme si le remplacant est en erreur
460     """
461     # Reinitialisation complete du compte-rendu d'erreurs
462     self.jdc_aux.cr=self.jdc_aux.CR()
463     # On remplit le dictionnaire des concepts produits inclus
464     # en retirant les concepts présents dans le  contexte initial
465     # On ajoute egalement le concept produit dans le sds_dict du parent
466     # sans verification car on est sur (verification integrée) que
467     # le nommage est possible
468     j_context=self.jdc_aux.get_contexte_avant(None)
469     self.g_context.clear()
470     context_ini=self.jdc_aux.context_ini
471     for k,v in j_context.items():
472        if not context_ini.has_key(k) or context_ini[k] != v:
473            self.g_context[k]=v
474            self.parent.sds_dict[k]=v
475     # On recupere le contexte courant
476     self.current_context=self.jdc_aux.current_context
477     self.index_etape_courante=self.jdc_aux.index_etape_courante
478     self.contexte_fichier_init = j_context
479     self.fichier_err = None
480
481     # On enregistre la modification de fichier
482     self.init_modif()
483     self.state="undetermined"
484     self.record_unite()
485     # Le contexte du parent doit etre reinitialise car les concepts produits ont changé
486     self.parent.reset_context()
487
488     # On remplace les anciens concepts par les nouveaux (y compris ajouts 
489     # et suppression) et on propage les modifications aux etapes precedentes et suivantes
490     # reevalue_sd_jdc construit la liste des differences entre les contextes contexte_fichier_init
491     # et old_contexte_fichier_init et effectue les destructions et remplacements de concept
492     # necessaires
493     self.old_contexte_fichier_init=self.old_context
494     self.reevalue_sd_jdc()
495     self.fin_modif()
496     if self.old_jdc_aux:
497        self.old_jdc_aux.close()
498
499     self.jdc_aux.force_contexte(self.g_context)
500
501   def build_include(self,fichier,text):
502     import Extensions.jdc_include
503     self.JdC_aux=Extensions.jdc_include.JdC_include
504     # un include partage la table des unites avec son parent (jdc)
505     self.recorded_units=self.parent.recorded_units
506     self.build_jdcaux(fichier,text)
507
508   def build_poursuite(self,fichier,text):
509     import Extensions.jdc_include
510     self.JdC_aux=Extensions.jdc_include.JdC_poursuite
511     # une poursuite a sa propre table d'unites
512     self.recorded_units={}
513     self.build_jdcaux(fichier,text)
514
515   def build_jdcaux(self,fichier,text):
516     """
517          Cree un jdc auxiliaire initialise avec text. 
518          Initialise le nom du fichier associé avec fichier
519          N'enregistre pas d'association unite <-> fichier
520     """
521     self.fichier_ini = fichier
522     self.fichier_text= text
523     self.fichier_unite=None
524     self.fichier_err = None
525     try:
526        contexte = self.get_contexte_jdc(fichier,text)
527        if contexte is None :
528           # Impossible de construire le jdc auxiliaire (sortie par None)
529           # On simule une sortie par exception
530           raise Exception("Impossible de construire le jeu de commandes correspondant au fichier")
531        else:
532           # La construction du jdc auxiliaire est allée au bout
533           self.contexte_fichier_init = contexte
534        self.init_modif()
535        self.fin_modif()
536     except:
537        # Impossible de construire le jdc auxiliaire (sortie par exception)
538        l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
539        if self.jdc.appli is not None:
540           self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
541                                         message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
542                                        )
543        self.g_context={}
544        self.etapes=[]
545        self.jdc_aux=None
546        self.fichier_err = string.join(l)
547        self.contexte_fichier_init={}
548        self.init_modif()
549        self.fin_modif()
550        raise
551
552   def make_contexte_include(self,fichier,text):
553     """
554         Cette méthode sert à créer un contexte en interprétant un texte source Python.
555     """
556     #print "make_contexte_include",fichier
557     # on récupère le contexte d'un nouveau jdc dans lequel on interprete text
558     contexte = self.get_contexte_jdc(fichier,text)
559     if contexte == None :
560       raise Exception("Impossible de construire le jeu de commandes correspondant au fichier")
561     else:
562       # Pour les macros de type include : INCLUDE, INCLUDE_MATERIAU et POURSUITE
563       # l'attribut g_context est un dictionnaire qui contient les concepts produits par inclusion
564       # l'attribut contexte_fichier_init est un dictionnaire qui contient les concepts produits
565       # en sortie de macro. g_context est obtenu en retirant de contexte_fichier_init les concepts
566       # existants en debut de macro contenus dans context_ini (dans get_contexte_jdc)
567       # g_context est utilisé pour avoir les concepts produits par la macro
568       # contexte_fichier_init est utilisé pour avoir les concepts supprimés par la macro
569       self.contexte_fichier_init = contexte
570
571   def reevalue_fichier_init_OBSOLETE(self):
572       """Recalcule les concepts produits par le fichier enregistre"""
573       #print "reevalue_fichier_init"
574       old_context=self.contexte_fichier_init
575       try:
576          self.make_contexte_include(self.fichier_ini ,self.fichier_text)
577       except:
578          l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
579          self.fichier_err = string.join(l)
580          self.g_context={}
581          self.etapes=[]
582          self.jdc_aux=None
583          self.old_contexte_fichier_init=old_context
584          self.contexte_fichier_init={}
585          self.reevalue_sd_jdc()
586          return
587
588       # L'evaluation s'est bien passee
589       self.fichier_err = None
590       self.old_contexte_fichier_init=old_context
591       self.reevalue_sd_jdc()
592
593   def update_fichier_init(self,unite):
594       """Reevalue le fichier init sans demander (dans la mesure du possible) a l'utilisateur 
595          les noms des fichiers
596          Ceci suppose que les relations entre unites et noms ont été memorisees préalablement
597          L'include a été initialisé précédemment. Le jdc auxiliaire existe.
598       """
599       #print "update_fichier_init",unite,self.fichier_unite 
600       self.old_contexte_fichier_init=self.contexte_fichier_init
601       old_fichier_ini=self.fichier_ini
602       if not hasattr(self,"jdc_aux"):self.jdc_aux=None
603       old_jdc_aux=self.jdc_aux
604
605       #print "update_fichier_init",self,self.parent,self.parent.recorded_units
606
607       if self.fichier_unite is None:
608          # L'unité n'était pas définie précédemment. On ne change que l'unite
609          #print "update_fichier_init","pas de changement dans include"
610          self.fichier_unite=unite
611          return
612       elif unite == self.fichier_unite :
613          # L'unité n'a pas changé
614          #print "update_fichier_init","pas de changement dans include 3"
615          return
616       elif unite != self.fichier_unite :
617          # L'unité était définie précédemment. On remplace l'include 
618          #
619          f,text=self.get_file_memo(unite=unite,fic_origine=self.parent.nom)
620          if f is None:
621             # Le fichier associé n'a pas pu etre defini
622             # on change l'unite associée mais pas l'include
623             #print "update_fichier_init","pas de changement dans include 2"
624             self.fichier_unite=unite
625             return
626          else:
627             self.fichier_ini = f
628             self.fichier_text=text
629             self.fichier_unite=unite
630          #print "update_fichier_init",self.recorded_units
631
632       #print "update_fichier_init",self.fichier_ini,self.fichier_text,self.fichier_unite
633
634       if old_fichier_ini == self.fichier_ini:
635          # Le fichier inclus n'a pas changé. On ne recrée pas le contexte
636          # mais on enregistre le changement d'association unite <-> fichier
637          #print "update_fichier_init.fichier inchange",self.jdc_aux.context_ini
638          self.parent.record_unit(unite,self)
639          return
640
641       try:
642         self.fichier_err=None
643         self.make_contexte_include(self.fichier_ini,self.fichier_text)
644         # Les 3 attributs fichier_ini fichier_text recorded_units doivent etre corrects
645         # avant d'appeler change_unit
646       except:
647         # Erreurs lors de l'evaluation de text dans un JDC auxiliaire
648         l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
649         # On conserve la memoire du nouveau fichier
650         # mais on n'utilise pas les concepts crees par ce fichier
651         # on met l'etape en erreur : fichier_err=string.join(l)
652         self.fichier_err=string.join(l)
653         self.g_context={}
654         self.etapes=[]
655         self.jdc_aux=None
656         self.contexte_fichier_init={}
657
658       if old_jdc_aux:
659          old_jdc_aux.close()
660       self.parent.record_unit(unite,self)
661       # Le contexte du parent doit etre reinitialise car les concepts 
662       # produits ont changé
663       self.parent.reset_context()
664       # Si des concepts ont disparu lors du changement de fichier, on 
665       # demande leur suppression
666       self.reevalue_sd_jdc()
667       #print "update_fichier_init",self.jdc_aux.context_ini.keys()
668
669   def record_unite(self):
670       #print "record_unite",self.nom
671       if self.nom == "POURSUITE":
672          self.parent.record_unit(None,self)
673       else:
674          if hasattr(self,'fichier_unite') : 
675             self.parent.record_unit(self.fichier_unite,self)
676
677   def get_file_memo(self,unite=None,fic_origine=''):
678       """Retourne le nom du fichier et le source correspondant a l'unite unite
679          Initialise en plus recorded_units
680       """
681       #print "get_file_memo",unite,fic_origine,self,self.parent
682       #print self.parent.recorded_units
683       if unite is None:
684          # On est dans le cas d'une poursuite. On ne reutilise aucune unite de parent
685          units={}
686       else:
687          # On est dans le cas d'un include. On reutilise toutes les unites de parent
688          units=self.parent.recorded_units
689
690       if self.parent.recorded_units.has_key(unite):
691          f,text,units=self.parent.recorded_units[unite]
692       elif self.jdc :
693          f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
694       else:
695          f,text=None,None
696
697       self.recorded_units=units
698       if f is None and self.jdc.appli:
699          self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
700                           message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini")
701       return f,text
702
703   def update_context(self,d):
704       """
705          Met à jour le contexte contenu dans le dictionnaire d
706          Une MACRO_ETAPE peut ajouter plusieurs concepts dans le contexte
707          Une fonction enregistree dans op_init peut egalement modifier le contexte
708       """
709       #print "update_context",self,self.nom,d.keys()
710       if hasattr(self,"jdc_aux") and self.jdc_aux:
711             #ATTENTION: update_context NE DOIT PAS appeler reset_context
712             # car il appelle directement ou indirectement update_context
713             # equivalent a reset_context. Evite les recursions
714             self.jdc_aux.context_ini=d.copy()
715             self.jdc_aux.current_context={}
716             self.jdc_aux.index_etape_courante=0
717             #ATTENTION: il ne faut pas utiliser self.jdc_aux.get_contexte_avant
718             #car cet appel conduit a des remontées multiples incohérentes dans le
719             # ou les parents. 
720             #get_context_avant appelle update_context qui NE DOIT PAS appeler get_contexte_avant
721             #On n'a besoin que d'un update local connaissant
722             # le contexte amont : d qui sert a reinitialiser self.context_ini
723             for e in self.etapes:
724                 e.update_context(d)
725             return
726
727       if type(self.definition.op_init) == types.FunctionType:
728         apply(self.definition.op_init,(self,d))
729       if self.sd != None:d[self.sd.nom]=self.sd
730       for co in self.sdprods:
731         d[co.nom]=co
732       #print "update_context.fin",d.keys()
733
734 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
735   def copy(self):
736       etape=Noyau.N_MACRO_ETAPE.MACRO_ETAPE.copy(self)
737       if hasattr(etape,"etapes") :etape.etapes=[]
738       if hasattr(etape,"jdc_aux") : 
739          etape.jdc_aux=None
740          del etape.fichier_ini
741       return etape
742
743   def supprime(self):
744       #print "supprime",self
745       if hasattr(self,"jdc_aux") and self.jdc_aux:
746          self.jdc_aux.supprime_aux()
747          self.jdc_aux=None
748       Noyau.N_MACRO_ETAPE.MACRO_ETAPE.supprime(self)
749   #    self.contexte_fichier_init={}
750   #    self.old_contexte_fichier_init={}
751   #    self.g_context={}
752   #    self.current_context={}
753   #    self.etapes=[]
754   #    self.mc_liste=[]
755
756 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
757   def get_file(self,unite=None,fic_origine=''):
758       """Retourne le nom du fichier et le source correspondant a l'unite unite
759       """
760       if self.jdc :
761          f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
762       else:
763          f,text=None,None
764       return f,text
765
766
767   def make_include2(self,fichier=None):
768       # gestion de l unicite SVP
769       unite=999
770
771       if hasattr(self,'fichier_ini') : return
772       reevalue=0
773       if hasattr(self,'old_context_fichier_init' ):
774          reevalue=1
775          for concept in self.old_context_fichier_init.values():
776              self.jdc.delete_concept(concept)
777
778       if fichier == None :
779          fichier=str(self.jdc.appli.get_file_variable())
780          if fichier  == str("") : 
781            self.fichier_ini="badfile"
782            self.fichier_text=""
783            self.fichier_err="Le fichier n est pas defini"
784            self.parent.record_unit(999,self)
785            try :
786               MCFils=self.get_child('FileName')
787               MCFils.set_valeur(None)
788            except :
789               pass
790            raise Exception(self.fichier_err)
791
792       self.fichier_ini  = fichier
793       self.fichier_text = ""
794       self.contexte_fichier_init={}
795       self.fichier_unite=999
796       self.fichier_err=None
797       nbVariableOut=0
798       try :
799          from openturns import WrapperFile
800          monWrapper=WrapperFile(fichier)
801          data=monWrapper.getWrapperData()
802          maVariableListe=data.getVariableList()
803          nbVariables=maVariableListe.getSize()
804          for i in range(nbVariables) :
805              nom=maVariableListe[i].id_
806              type=maVariableListe[i].type_
807              if type :
808                #ligneTexte="%s=DETERMINISTICVARIABLE(N='%s',T='out',R=%d);\n" % (nom, nom, i)
809                ligneTexte=""
810                nbVariableOut=nbVariableOut+1
811              else :
812                ligneTexte="%s=DETERMINISTICVARIABLE(N='%s',T='in',R=%d);\n" % (nom, nom, i)
813              self.fichier_text = self.fichier_text + ligneTexte
814       except:
815          self.make_incl2_except()
816          raise
817
818       if nbVariableOut != 1 :
819          print nbVariableOut ,"nbVariableOut"
820          self.make_incl2_except(mess="le fichier doit contenir une unique variable de sortie")
821          raise
822
823       try:
824          import Extensions.jdc_include
825          self.JdC_aux=Extensions.jdc_include.JdC_include
826       except:
827          traceback.print_exc()
828          self.make_incl2_except()
829          raise
830       
831       try:
832          self.make_contexte_include(self.fichier_ini ,self.fichier_text)
833          self.old_context_fichier_init=self.contexte_fichier_init
834          self.parent.record_unit(unite,self)
835          try :
836             MCFils=self.get_child('FileName')
837             MCFils.set_valeur(fichier)
838          except :
839             pass
840       except:
841          self.make_incl2_except()
842
843       # recalcul validite pour la matrice eventuelle
844       if reevalue :
845          for e in self.jdc.etapes:
846            if e.nom == "VARIABLE" :
847               e.state="modified"
848               try :
849                  mc=e.get_child('ModelVariable') 
850                  mc.state="modified"
851               except :
852                  pass
853            if e.nom == "CORRELATION" :
854               e.state="modified"
855               try :
856                  mc=e.get_child('Matrix') 
857                  mc.state="modified"
858                  mcFeuille=mc.get_child('CorrelationMatrix')
859                  mcFeuille.state="modified"
860               except :
861                  pass
862               e.isvalid()
863
864   def make_incl2_except(self,mess=None):
865          l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
866          if self.jdc.appli is not None:
867              if mess == None :
868                      self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
869                                             message="Le contenu de ce fichier ne sera pas pris en compte\n"+string.join(l)
870                                            )
871              else :
872                      self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
873                                             message=mess )
874          #self.parent.record_unit(unite,self)
875          self.g_context={}
876          self.etapes=[]
877          self.jdc_aux=None
878          self.fichier_err = string.join(l)
879          self.contexte_fichier_init={}
880          try :
881             MCFils=self.get_child('FileName')
882             MCFils.set_valeur(None)
883          except :
884             pass
885
886
887 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
888   def make_include(self,unite=None):
889       """
890           Inclut un fichier dont l'unite logique est unite
891           Cette methode est appelee par la fonction sd_prod de la macro INCLUDE
892           Si l'INCLUDE est invalide, la methode doit produire une exception 
893           Sinon on retourne None. Les concepts produits par l'INCLUDE sont
894           pris en compte par le JDC parent lors du calcul du contexte (appel de ???)
895       """
896       #print "make_include",unite
897       # On supprime l'attribut unite qui bloque l'evaluation du source de l'INCLUDE
898       # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini
899       # Si unite n'a pas de valeur, l'etape est forcement invalide. On peut retourner None
900       if not unite : return
901
902       if not hasattr(self,'fichier_ini') : 
903          # Si le fichier n'est pas defini on le demande
904          f,text=self.get_file_memo(unite=unite,fic_origine=self.parent.nom)
905          # On memorise le fichier retourne
906          self.fichier_ini  = f
907          self.fichier_text = text
908          self.contexte_fichier_init={}
909          self.fichier_unite=unite
910          self.fichier_err=None
911          try:
912            import Extensions.jdc_include
913          except:
914            traceback.print_exc()
915            raise
916          self.JdC_aux=Extensions.jdc_include.JdC_include
917
918          #print "make_include",self.fichier_ini,self.fichier_text 
919          if f is None and not text:
920              self.fichier_err="Le fichier INCLUDE n est pas defini"
921              self.parent.record_unit(unite,self)
922              raise Exception(self.fichier_err)
923
924          try:
925            self.make_contexte_include(self.fichier_ini ,self.fichier_text)
926            self.parent.record_unit(unite,self)
927          except:
928            l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
929            if self.jdc.appli:
930               self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
931                                             message="Le contenu de ce fichier ne sera pas pris en compte\n"+string.join(l)
932                                            )
933            self.parent.record_unit(unite,self)
934            self.g_context={}
935            self.etapes=[]
936            self.jdc_aux=None
937            self.fichier_err = string.join(l)
938            self.contexte_fichier_init={}
939            raise
940
941       else:
942          # Si le fichier est deja defini on ne reevalue pas le fichier
943          # et on leve une exception si une erreur a été enregistrée
944          self.update_fichier_init(unite)
945          self.fichier_unite=unite
946          if self.fichier_err is not None: raise Exception(self.fichier_err)
947         
948
949 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
950   def make_contexte(self,fichier,text):
951     """
952         Cette méthode sert à créer un contexte pour INCLUDE_MATERIAU
953         en interprétant un texte source Python
954         Elle est appelee par la fonction sd_prod d'INCLUDE_MATERIAU
955     """
956     #print "make_contexte",fichier
957     # On supprime l'attribut mat qui bloque l'evaluation du source de l'INCLUDE_MATERIAU
958     # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini
959     if hasattr(self,'mat'):del self.mat
960     if not hasattr(self,'fichier_ini') or self.fichier_ini != fichier or self.fichier_mater != self.nom_mater: 
961        # le fichier est nouveau ou change
962        self.fichier_ini =fichier
963        self.fichier_unite =fichier
964        self.fichier_mater=self.nom_mater
965        self.fichier_text=text
966        self.fichier_err=None 
967        self.contexte_fichier_init={}
968        # On specifie la classe a utiliser pour le JDC auxiliaire
969        try:
970          import Extensions.jdc_include
971          self.JdC_aux=Extensions.jdc_include.JdC_include
972        except:
973          raise
974        try:
975           self.make_contexte_include(self.fichier_ini ,self.fichier_text)
976           if not self.g_context.has_key(self.nom_mater):
977              #Pour permettre de lire un jeu de commandes avec des INCLUDE_MATERIAU errones
978              self.g_context[self.nom_mater]=None
979              if self.parent: self.parent.g_context[self.nom_mater]=None
980        except:
981           l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
982           self.fichier_err = string.join(l)
983           self.g_context={}
984           #Pour permettre de lire un jeu de commandes avec des INCLUDE_MATERIAU errones
985           if self.parent:
986               self.parent.g_context[self.nom_mater]=None
987           self.g_context[self.nom_mater]=None
988           #-------------
989           self.etapes=[]
990           self.jdc_aux=None
991           self.contexte_fichier_init={}
992           raise
993     else:
994        # le fichier est le meme on ne le reevalue pas
995        # et on leve une exception si une erreur a été enregistrée
996        if self.fichier_err is not None: raise Exception(self.fichier_err)
997
998 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
999   def update_sdprod(self,cr='non'):
1000      # Cette methode peut etre appelee dans EFICAS avec des mots cles de 
1001      # la commande modifies. Ceci peut conduire a la construction ou
1002      # a la reconstruction d'etapes dans le cas d'INCLUDE ou d'INCLUDE_MATERIAU
1003      # Il faut donc positionner le current_step avant l'appel
1004      CONTEXT.unset_current_step()
1005      CONTEXT.set_current_step(self)
1006      valid=Validation.V_MACRO_ETAPE.MACRO_ETAPE.update_sdprod(self,cr=cr)
1007      CONTEXT.unset_current_step()
1008      return valid
1009
1010 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro 
1011   def Build_sd(self,nom):
1012       """
1013            Methode de Noyau surchargee pour poursuivre malgre tout
1014            si une erreur se produit pendant la creation du concept produit
1015       """
1016       try:
1017          sd=Noyau.N_MACRO_ETAPE.MACRO_ETAPE.Build_sd(self,nom)
1018       except AsException,e:
1019          # Une erreur s'est produite lors de la construction du concept
1020          # Comme on est dans EFICAS, on essaie de poursuivre quand meme
1021          # Si on poursuit, on a le choix entre deux possibilités :
1022          # 1. on annule la sd associée à self
1023          # 2. on la conserve mais il faut la retourner
1024          # On choisit de l'annuler
1025          # En plus il faut rendre coherents sdnom et sd.nom
1026          self.sd=None
1027          self.sdnom=None
1028          self.state="unchanged"
1029          self.valid=0
1030
1031       return self.sd
1032
1033 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro 
1034   def make_poursuite(self):
1035       """ Cette methode est appelée par la fonction sd_prod de la macro POURSUITE
1036       """
1037       #print "make_poursuite"
1038       if not hasattr(self,'fichier_ini') :
1039          # Si le fichier n'est pas defini on le demande
1040          f,text=self.get_file_memo(fic_origine=self.parent.nom)
1041          # On memorise le fichier retourne
1042          self.fichier_ini = f
1043          self.fichier_unite = None
1044          self.fichier_text = text
1045          self.fichier_err=None
1046          try:
1047            import Extensions.jdc_include
1048          except:
1049            traceback.print_exc()
1050            raise
1051          self.JdC_aux=Extensions.jdc_include.JdC_poursuite
1052          self.contexte_fichier_init={}
1053          #print "make_poursuite",self.fichier_ini,self.fichier_text
1054
1055          if f is None:
1056              self.fichier_err="Le fichier POURSUITE n'est pas defini"
1057              self.jdc_aux=None
1058              self.parent.record_unit(None,self)
1059              raise Exception(self.fichier_err)
1060
1061          try:
1062            self.make_contexte_include(self.fichier_ini,self.fichier_text)
1063            self.parent.record_unit(None,self)
1064          except:
1065            l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
1066            if self.jdc.appli:
1067               self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier poursuite",
1068                                             message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
1069                                            )
1070            self.parent.record_unit(None,self)
1071            self.g_context={}
1072            self.etapes=[]
1073            self.jdc_aux=None
1074            self.fichier_err = string.join(l)
1075            self.contexte_fichier_init={}
1076            raise
1077
1078       else:
1079          # Si le fichier est deja defini on ne reevalue pas le fichier
1080          # et on leve une exception si une erreur a été enregistrée
1081          self.update_fichier_init(None)
1082          if self.fichier_err is not None: raise Exception(self.fichier_err)