]> SALOME platform Git repositories - tools/eficas.git/blob - Ihm/I_MACRO_ETAPE.py
Salome HOME
CCAR: modifications pour :
[tools/eficas.git] / Ihm / I_MACRO_ETAPE.py
1 # -*- coding: utf-8 -*-
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 from Noyau.N_ASSD import ASSD
30
31 # import rajoutés suite à l'ajout de Build_sd --> à résorber
32 import Noyau, Validation.V_MACRO_ETAPE
33 from Noyau import N_Exception
34 from Noyau.N_Exception import AsException
35 import Accas # attention aux imports circulaires
36 # fin import à résorber
37
38 class MACRO_ETAPE(I_ETAPE.ETAPE):
39
40   def __init__(self):
41       self.typret=None
42       self.recorded_units={}
43
44   def get_sdprods(self,nom_sd):
45     """ 
46          Fonction : retourne le concept produit par l etape de nom nom_sd
47          s il existe sinon None
48     """
49     if self.sd and self.sd.nom == nom_sd :return self.sd
50     for co in self.sdprods:
51       if co.nom == nom_sd:return co
52     if type(self.definition.op_init) == types.FunctionType:
53       d={}
54       apply(self.definition.op_init,(self,d))
55       return d.get(nom_sd,None)
56     return None
57
58   def get_contexte_jdc(self,fichier,text):
59     """ 
60          Interprète text comme un texte de jdc et retourne le 
61          contexte final
62          cad le dictionnaire des sd disponibles à la dernière étape
63          Si text n'est pas un texte de jdc valide, retourne None
64          ou leve une exception
65          --> utilisée par ops.POURSUITE et INCLUDE
66     """
67     #print "get_contexte_jdc"
68     try:
69        # on essaie de créer un objet JDC auxiliaire avec un contexte initial
70        # Attention get_contexte_avant retourne un dictionnaire qui contient
71        # le contexte courant. Ce dictionnaire est reactualise regulierement.
72        # Si on veut garder l'etat du contexte fige, il faut en faire une copie.
73        context_ini = self.parent.get_contexte_avant(self).copy()
74
75        # Indispensable avant de creer un nouveau JDC
76        CONTEXT.unset_current_step()
77        args=self.jdc.args
78        prefix_include=None
79        if hasattr(self,'prefix'):
80           prefix_include=self.prefix
81        # ATTENTION : le dictionnaire recorded_units sert à memoriser les unites des 
82        # fichiers inclus. Il est preferable de garder le meme dictionnaire pendant
83        # tout le traitement et de ne pas le reinitialiser brutalement (utiliser 
84        # clear plutot) si on ne veut pas perdre la memoire des unites.
85        # En principe si la memorisation est faite au bon moment il n'est pas necessaire
86        # de prendre cette precaution mais ce n'est pas vrai partout.
87        old_recorded_units=self.recorded_units.copy()
88        #print "get_contexte_jdc",id(self.recorded_units)
89        #self.recorded_units.clear()
90
91        j=self.JdC_aux( procedure=text, nom=fichier,
92                                 appli=self.jdc.appli,
93                                 cata=self.jdc.cata,
94                                 cata_ord_dico=self.jdc.cata_ordonne_dico,
95                                 context_ini = context_ini,
96                                 jdc_pere=self.jdc,etape_include=self,
97                                 prefix_include=prefix_include,
98                                 recorded_units=self.recorded_units,
99                                 old_recorded_units=old_recorded_units,**args)
100
101        j.analyse()
102        # On récupère les étapes internes (pour validation)
103        self.etapes=j.etapes
104        self.jdc_aux=j
105        #print "get_contexte_jdc",id(self.etapes)
106     except:
107        traceback.print_exc()
108        # On force le contexte (etape courante) à self
109        CONTEXT.unset_current_step()
110        CONTEXT.set_current_step(self)
111        return None
112
113     if not j.cr.estvide():
114        # Erreurs dans l'INCLUDE. On garde la memoire du fichier 
115        # mais on n'insere pas les concepts
116        # On force le contexte (etape courante) à self
117        CONTEXT.unset_current_step()
118        CONTEXT.set_current_step(self)
119        raise Exception("Impossible de relire le fichier\n"+str(j.cr))
120
121     if not j.isvalid():
122        # L'INCLUDE n'est pas valide.
123        # on produit un rapport d'erreurs
124        # On force le contexte (etape courante) à self
125        cr=j.report()
126        CONTEXT.unset_current_step()
127        CONTEXT.set_current_step(self)
128        raise Exception("Le fichier include contient des erreurs\n"+str(cr))
129
130     # Si aucune erreur rencontrée
131     # On recupere le contexte de l'include verifie
132     #print "context_ini",j.context_ini
133     #print "g_context",j.g_context
134     try:
135        j_context=j.get_verif_contexte()
136     except:
137        CONTEXT.unset_current_step()
138        CONTEXT.set_current_step(self)
139        raise
140
141     #print "context_ini",j.context_ini
142
143     # On remplit le dictionnaire des concepts produits inclus
144     # en retirant les concepts présents dans le  contexte initial
145     # On ajoute egalement le concept produit dans le sds_dict du parent
146     # sans verification car on est sur (verification integrée) que 
147     # le nommage est possible
148     self.g_context.clear()
149     for k,v in j_context.items():
150        if not context_ini.has_key(k) or context_ini[k] != v:
151            self.g_context[k]=v
152            self.parent.sds_dict[k]=v
153
154
155     # On recupere le contexte courant
156     self.current_context=j.current_context
157     self.index_etape_courante=j.index_etape_courante
158     self.jdc_aux=j
159
160     # XXX j.supprime() ???
161     # On rétablit le contexte (etape courante) à self
162     CONTEXT.unset_current_step()
163     CONTEXT.set_current_step(self)
164     #print "context_ini",self.jdc_aux.context_ini
165
166     return j_context
167
168   def reevalue_sd_jdc(self):
169      """
170          Avec la liste des SD qui ont été supprimées, propage la 
171          disparition de ces SD dans toutes les étapes et descendants
172      """
173      #print "reevalue_sd_jdc"
174      l_sd_supp,l_sd_repl = self.diff_contextes()
175      for sd in l_sd_supp:
176         self.parent.delete_concept_after_etape(self,sd)
177      for old_sd,sd in l_sd_repl:
178         self.parent.replace_concept_after_etape(self,old_sd,sd)
179
180   def diff_contextes(self):
181      """ 
182          Réalise la différence entre les 2 contextes 
183          old_contexte_fichier_init et contexte_fichier_init
184          cad retourne la liste des sd qui ont disparu ou ne derivent pas 
185          de la meme classe et des sd qui ont ete remplacees
186      """
187      if not hasattr(self,'old_contexte_fichier_init'):return [],[]
188      l_sd_suppressed = []
189      l_sd_replaced = []
190      for old_key in self.old_contexte_fichier_init.keys():
191        if not self.contexte_fichier_init.has_key(old_key):
192          if isinstance(self.old_contexte_fichier_init[old_key],ASSD):
193            l_sd_suppressed.append(self.old_contexte_fichier_init[old_key])
194        else:
195          if isinstance(self.old_contexte_fichier_init[old_key],ASSD):
196             # Un concept de meme nom existe
197             old_class=self.old_contexte_fichier_init[old_key].__class__
198             if not isinstance(self.contexte_fichier_init[old_key],old_class):
199                # S'il n'est pas d'une classe derivee, on le supprime
200                l_sd_suppressed.append(self.old_contexte_fichier_init[old_key])
201             else:
202                l_sd_replaced.append((self.old_contexte_fichier_init[old_key],self.contexte_fichier_init[old_key]))
203      return l_sd_suppressed,l_sd_replaced
204       
205   def control_sdprods(self,d):
206       """
207           Cette methode doit updater le contexte fournit par
208           l'appelant en argument (d) en fonction de sa definition
209           tout en verifiant que ses concepts produits ne sont pas
210           deja definis dans le contexte
211       """
212       if hasattr(self,"fichier_unite"):
213          self.update_fichier_init(self.fichier_unite)
214          self.init_modif()
215
216       if type(self.definition.op_init) == types.FunctionType:
217         apply(self.definition.op_init,(self,d))
218       if self.sd:
219         if d.has_key(self.sd.nom):
220            # Le concept est deja defini
221            if self.reuse and self.reuse is d[self.sd.nom]:
222               # Le concept est reutilise : situation normale
223               pass
224            else:
225               # Redefinition du concept, on l'annule
226               #XXX on pourrait simplement annuler son nom pour conserver les objets
227               # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
228               self.sd=self.reuse=self.sdnom=None
229               self.init_modif()
230         else:
231            # Le concept n'est pas defini, on peut updater d
232            d[self.sd.nom]=self.sd
233       # On verifie les concepts a droite du signe =
234       for co in self.sdprods:
235         if d.has_key(co.nom) and co is not d[co.nom] :
236            self.delete_concept(co)
237         else:
238            d[co.nom]=co
239        
240
241   def supprime_sdprods(self):
242       """
243           Fonction: Lors de la destruction de la macro-etape, detruit tous les concepts produits
244           Un opérateur n a qu un concept produit
245           Une procedure n'en a aucun
246           Une macro en a en général plus d'un
247       """
248       #print "supprime_sdprods"
249       if not self.is_reentrant() :
250          # l'étape n'est pas réentrante
251          # le concept retourné par l'étape est à supprimer car il était
252          # créé par l'étape
253          if self.sd != None :
254             self.parent.del_sdprod(self.sd)
255             self.parent.delete_concept(self.sd)
256       # On détruit les concepts à droite du signe =
257       for co in self.sdprods:
258          self.parent.del_sdprod(co)
259          self.parent.delete_concept(co)
260       # Si la macro a des etapes et des concepts inclus, on les detruit
261       for nom_sd,co in self.g_context.items():
262          if not isinstance(co,ASSD):continue
263          self.parent.del_sdprod(co)
264          self.parent.delete_concept(co)
265       # On met g_context à blanc
266       self.g_context={}
267
268   def delete_concept(self,sd):
269       """
270           Fonction : Mettre a jour les mots cles de l etape et eventuellement
271           le concept produit si reuse suite à la disparition du concept sd
272           Seuls les mots cles simples MCSIMP font un traitement autre
273           que de transmettre aux fils
274       """
275       #print "delete_concept",sd
276       I_ETAPE.ETAPE.delete_concept(self,sd)
277       for etape in self.etapes:
278          etape.delete_concept(sd)
279
280   def replace_concept(self,old_sd,sd):
281       """
282           Fonction : Mettre a jour les mots cles de l etape et le concept produit si reuse 
283           suite au remplacement  du concept old_sd par sd
284       """
285       #print "replace_concept",old_sd,sd
286       I_ETAPE.ETAPE.replace_concept(self,old_sd,sd)
287       for etape in self.etapes:
288          etape.replace_concept(sd)
289          
290   def change_fichier_init(self,new_fic,text):
291     """
292        Tente de changer le fichier include. Le precedent include est conservé
293        dans old_xxx
294     """
295     if not hasattr(self,'fichier_ini'):
296        self.fichier_ini=None
297        self.fichier_text=None
298        self.fichier_err="Le fichier n'est pas defini"
299        self.contexte_fichier_init={}
300        self.recorded_units={}
301        self.jdc_aux=None
302        self.fichier_unite="PasDefini"
303        import Extensions.jdc_include
304        self.JdC_aux=Extensions.jdc_include.JdC_include
305
306     self.old_fic = self.fichier_ini
307     self.old_text = self.fichier_text
308     self.old_err = self.fichier_err
309     self.old_context=self.contexte_fichier_init
310     self.old_units=self.recorded_units
311     self.old_etapes=self.etapes
312     self.old_jdc_aux=self.jdc_aux
313
314     self.fichier_ini = new_fic
315     self.fichier_text=text
316
317     try:
318        self.make_contexte_include(new_fic,text)
319     except:
320        l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
321        self.fichier_err=string.join(l)
322        raise
323
324     # L'evaluation de text dans un JDC auxiliaire s'est bien passé
325     # on peut poursuivre le traitement
326     self.init_modif()
327     self.state="undetermined"
328     self.fichier_err=None
329     # On enregistre la modification de fichier
330     self.record_unite()
331     # Le contexte du parent doit etre reinitialise car les concepts produits ont changé
332     self.parent.reset_context()
333
334     # Si des concepts ont disparu lors du changement de fichier, on demande leur suppression
335     self.old_contexte_fichier_init=self.old_context
336     self.reevalue_sd_jdc()
337
338     self.fin_modif()
339
340   def restore_fichier_init(self):
341     """
342        Restaure le fichier init enregistre dans old_xxx
343     """
344     self.fichier_ini=self.old_fic
345     self.fichier_text=self.old_text
346     self.fichier_err=self.old_err
347     self.contexte_fichier_init=self.old_context
348     self.recorded_units=self.old_units
349     self.etapes=self.old_etapes
350     self.jdc_aux=self.old_jdc_aux
351
352   def force_fichier_init(self):
353     """
354        Force le fichier init en erreur
355     """
356     # On conserve la memoire du nouveau fichier
357     # mais on n'utilise pas les concepts crees par ce fichier
358     # on met l'etape en erreur : fichier_err=string.join(l)
359     self.init_modif()
360     # On enregistre la modification de fichier
361     self.record_unite()
362     #self.etapes=[]
363     self.g_context={}
364     # Le contexte du parent doit etre reinitialise car les concepts produits ont changé
365     self.parent.reset_context()
366
367     self.old_contexte_fichier_init=self.old_context
368     self.contexte_fichier_init={}
369     self.reevalue_sd_jdc()
370
371     self.fin_modif()
372
373   def make_contexte_include(self,fichier,text):
374     """
375         Cette méthode sert à créer un contexte en interprétant un texte source
376         Python
377     """
378     #print "make_contexte_include"
379     # on récupère le contexte d'un nouveau jdc dans lequel on interprete text
380     contexte = self.get_contexte_jdc(fichier,text)
381     if contexte == None :
382       raise Exception("Impossible de construire le jeu de commandes correspondant au fichier")
383     else:
384       # Pour les macros de type include : INCLUDE, INCLUDE_MATERIAU et POURSUITE
385       # l'attribut g_context est un dictionnaire qui contient les concepts produits par inclusion
386       # l'attribut contexte_fichier_init est un dictionnaire qui contient les concepts produits
387       # en sortie de macro. g_context est obtenu en retirant de contexte_fichier_init les concepts
388       # existants en debut de macro contenus dans context_ini (dans get_contexte_jdc)
389       # g_context est utilisé pour avoir les concepts produits par la macro
390       # contexte_fichier_init est utilisé pour avoir les concepts supprimés par la macro
391       self.contexte_fichier_init = contexte
392
393   def reevalue_fichier_init_OBSOLETE(self):
394       """Recalcule les concepts produits par le fichier enregistre"""
395       #print "reevalue_fichier_init"
396       old_context=self.contexte_fichier_init
397       try:
398          self.make_contexte_include(self.fichier_ini ,self.fichier_text)
399       except:
400          l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
401          self.fichier_err = string.join(l)
402          #self.etapes=[]
403          self.g_context={}
404
405          self.old_contexte_fichier_init=old_context
406          self.contexte_fichier_init={}
407          self.reevalue_sd_jdc()
408          return
409
410       # L'evaluation s'est bien passee
411       self.fichier_err = None
412       self.old_contexte_fichier_init=old_context
413       self.reevalue_sd_jdc()
414       #print "reevalue_fichier_init",self.jdc_aux.context_ini
415
416   def update_fichier_init(self,unite):
417       """Reevalue le fichier init sans demander (dans la mesure du possible) a l'utilisateur 
418          les noms des fichiers
419          Ceci suppose que les relations entre unites et noms ont été memorisees préalablement
420       """
421       #print "update_fichier_init",unite
422       self.fichier_err=None
423       self.old_contexte_fichier_init=self.contexte_fichier_init
424       old_fichier_ini=self.fichier_ini
425
426       #print "update_fichier_init",self,self.parent,self.parent.recorded_units
427
428       #if unite != self.fichier_unite or not self.parent.recorded_units.has_key(unite):
429       if not self.parent.recorded_units.has_key(unite):
430          # Nouvelle unite
431          f,text=self.get_file(unite=unite,fic_origine=self.parent.nom)
432          units={}
433          if f is not None:
434             self.fichier_ini = f
435             self.fichier_text=text
436          self.recorded_units=units
437          if self.fichier_ini is None and self.jdc.appli:
438             self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
439                      message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini")
440       else:
441          # Unite existante
442          f,text,units=self.parent.recorded_units[unite]
443          self.fichier_ini = f
444          self.fichier_text=text
445          self.recorded_units=units
446
447       if self.fichier_ini is None:
448          # Le fichier n'est pas défini
449          self.fichier_err="Le fichier associé n'est pas défini"
450          self.parent.change_unit(unite,self,self.fichier_unite)
451          self.g_context={}
452          self.contexte_fichier_init={}
453          self.parent.reset_context()
454          self.reevalue_sd_jdc()
455          return
456
457       if old_fichier_ini == self.fichier_ini:
458          # Le fichier inclus n'a pas changé. On ne recrée pas le contexte
459          #print "update_fichier_init.fichier inchange",self.jdc_aux.context_ini
460          return
461
462       try:
463         self.make_contexte_include(self.fichier_ini,self.fichier_text)
464         # Les 3 attributs fichier_ini fichier_text recorded_units doivent etre corrects
465         # avant d'appeler change_unit
466         self.parent.change_unit(unite,self,self.fichier_unite)
467       except:
468         # Erreurs lors de l'evaluation de text dans un JDC auxiliaire
469         l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
470         # On conserve la memoire du nouveau fichier
471         # mais on n'utilise pas les concepts crees par ce fichier
472         # on met l'etape en erreur : fichier_err=string.join(l)
473         self.fichier_err=string.join(l)
474         self.parent.change_unit(unite,self,self.fichier_unite)
475         self.g_context={}
476         self.contexte_fichier_init={}
477
478       # Le contexte du parent doit etre reinitialise car les concepts 
479       # produits ont changé
480       self.parent.reset_context()
481       # Si des concepts ont disparu lors du changement de fichier, on 
482       # demande leur suppression
483       self.reevalue_sd_jdc()
484       #print "update_fichier_init",self.jdc_aux.context_ini
485
486   def record_unite(self):
487       if self.nom == "POURSUITE":
488          self.parent.record_unit(None,self)
489       else:
490          if hasattr(self,'fichier_unite') : 
491             self.parent.record_unit(self.fichier_unite,self)
492
493   def get_file_memo(self,unite=None,fic_origine=''):
494       """Retourne le nom du fichier et le source correspondant a l'unite unite
495          Initialise en plus recorded_units
496       """
497       #print "get_file_memo",unite,fic_origine,self,self.parent
498       #print self.parent.old_recorded_units
499       #print self.parent.recorded_units
500       if unite is None:
501          units={}
502       else:
503          units=self.parent.recorded_units
504       if self.parent.old_recorded_units.has_key(unite):
505          f,text,units=self.parent.old_recorded_units[unite]
506          #print id(self.recorded_units)
507          self.recorded_units=units
508          #print id(self.recorded_units)
509          return f,text
510       elif self.jdc :
511          f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
512       else:
513          f,text=None,None
514       self.recorded_units=units
515       if f is None and self.jdc.appli:
516          self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
517                           message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini")
518       return f,text
519
520 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
521   def get_file(self,unite=None,fic_origine=''):
522       """Retourne le nom du fichier et le source correspondant a l'unite unite
523          Initialise en plus recorded_units
524       """
525       #print "get_file",unite
526       units={}
527       if self.jdc :
528          f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
529       else:
530          f,text=None,None
531       self.recorded_units=units
532       return f,text
533
534 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
535   def make_include(self,unite=None):
536       """
537           Inclut un fichier dont l'unite logique est unite
538           Cette methode est appelee par la fonction sd_prod de la macro INCLUDE
539           Si l'INCLUDE est invalide, la methode doit produire une exception 
540           Sinon on retourne None. Les concepts produits par l'INCLUDE sont
541           pris en compte par le JDC parent lors du calcul du contexte (appel de ???)
542       """
543       #print "make_include",unite
544       # On supprime l'attribut unite qui bloque l'evaluation du source de l'INCLUDE
545       # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini
546       del self.unite
547       # Si unite n'a pas de valeur, l'etape est forcement invalide. On peut retourner None
548       if not unite : return
549
550       if not hasattr(self,'fichier_ini') : 
551          # Si le fichier n'est pas defini on le demande
552          f,text=self.get_file_memo(unite=unite,fic_origine=self.parent.nom)
553          # On memorise le fichier retourne
554          self.fichier_ini  = f
555          self.fichier_text = text
556          self.contexte_fichier_init={}
557          self.fichier_unite=unite
558          self.fichier_err=None
559          try:
560            import Extensions.jdc_include
561          except:
562            traceback.print_exc()
563            raise
564          self.JdC_aux=Extensions.jdc_include.JdC_include
565
566          if f is None:
567              self.fichier_err="Le fichier INCLUDE n est pas defini"
568              self.parent.record_unit(unite,self)
569              raise Exception(self.fichier_err)
570
571          try:
572            self.make_contexte_include(self.fichier_ini ,self.fichier_text)
573            self.parent.record_unit(unite,self)
574            #print "make_include.context_ini",self.jdc_aux.context_ini
575          except:
576            l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
577            if self.jdc.appli:
578               self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
579                                             message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
580                                            )
581            self.parent.record_unit(unite,self)
582            self.g_context={}
583            self.fichier_err = string.join(l)
584            self.contexte_fichier_init={}
585            raise
586
587       else:
588          # Si le fichier est deja defini on ne reevalue pas le fichier
589          # et on leve une exception si une erreur a été enregistrée
590          self.update_fichier_init(unite)
591          self.fichier_unite=unite
592          if self.fichier_err is not None: raise Exception(self.fichier_err)
593         
594
595 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
596   def make_contexte(self,fichier,text):
597     """
598         Cette méthode sert à créer un contexte pour INCLUDE_MATERIAU
599         en interprétant un texte source Python
600         Elle est appelee par la fonction sd_prd d'INCLUDE_MATERIAU
601     """
602     # On supprime l'attribut mat qui bloque l'evaluation du source de l'INCLUDE_MATERIAU
603     # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini
604     if hasattr(self,'mat'):del self.mat
605     self.fichier_ini =fichier
606     self.fichier_unite =fichier
607     self.fichier_text=text
608     self.fichier_err=None 
609     self.contexte_fichier_init={}
610     # On specifie la classe a utiliser pour le JDC auxiliaire
611     try:
612       import Extensions.jdc_include
613     except:
614       traceback.print_exc()
615       raise
616     self.JdC_aux=Extensions.jdc_include.JdC_include
617     try:
618        self.make_contexte_include(self.fichier_ini ,self.fichier_text)
619        self.parent.record_unit(self.fichier_unite,self)
620     except:
621        l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
622        self.fichier_err = string.join(l)
623        self.parent.record_unit(self.fichier_unite,self)
624        self.g_context={}
625        self.contexte_fichier_init={}
626        raise
627
628 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
629   def update_sdprod(self,cr='non'):
630      # Cette methode peut etre appelee dans EFICAS avec des mots cles de 
631      # la commande modifies. Ceci peut conduire a la construction ou
632      # a la reconstruction d'etapes dans le cas d'INCLUDE ou d'INCLUDE_MATERIAU
633      # Il faut donc positionner le current_step avant l'appel
634      CONTEXT.unset_current_step()
635      CONTEXT.set_current_step(self)
636      valid=Validation.V_MACRO_ETAPE.MACRO_ETAPE.update_sdprod(self,cr=cr)
637      CONTEXT.unset_current_step()
638      return valid
639
640 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro 
641   def Build_sd(self,nom):
642       """
643            Methode de Noyau surchargee pour poursuivre malgre tout
644            si une erreur se produit pendant la creation du concept produit
645       """
646       try:
647          sd=Noyau.N_MACRO_ETAPE.MACRO_ETAPE.Build_sd(self,nom)
648       except AsException,e:
649          # Une erreur s'est produite lors de la construction du concept
650          # Comme on est dans EFICAS, on essaie de poursuivre quand meme
651          # Si on poursuit, on a le choix entre deux possibilités :
652          # 1. on annule la sd associée à self
653          # 2. on la conserve mais il faut la retourner
654          # On choisit de l'annuler
655          # En plus il faut rendre coherents sdnom et sd.nom
656          self.sd=None
657          self.sdnom=None
658          self.state="unchanged"
659          self.valid=0
660
661       return self.sd
662
663 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro 
664   def make_poursuite(self):
665       """ Cette methode est appelée par la fonction sd_prod de la macro POURSUITE
666       """
667       #print "make_poursuite"
668       if not hasattr(self,'fichier_ini') :
669          # Si le fichier n'est pas defini on le demande
670          f,text=self.get_file_memo(fic_origine=self.parent.nom)
671          # On memorise le fichier retourne
672          self.fichier_ini = f
673          self.fichier_unite = None
674          self.fichier_text = text
675          self.fichier_err=None
676          try:
677            import Extensions.jdc_include
678          except:
679            traceback.print_exc()
680            raise
681          self.JdC_aux=Extensions.jdc_include.JdC_poursuite
682          self.contexte_fichier_init={}
683
684          if f is None:
685              self.fichier_err="Le fichier POURSUITE n'est pas defini"
686              self.parent.record_unit(None,self)
687              raise Exception(self.fichier_err)
688
689          try:
690            self.make_contexte_include(self.fichier_ini,self.fichier_text)
691            self.parent.record_unit(None,self)
692          except:
693            l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
694            if self.jdc.appli:
695               self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier poursuite",
696                                             message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
697                                            )
698            self.parent.record_unit(None,self)
699            self.g_context={}
700            self.fichier_err = string.join(l)
701            self.contexte_fichier_init={}
702            raise
703
704       else:
705          # Si le fichier est deja defini on ne reevalue pas le fichier
706          # et on leve une exception si une erreur a été enregistrée
707          self.update_fichier_init(None)
708          if self.fichier_err is not None: raise Exception(self.fichier_err)
709
710 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro 
711   def type_sdprod(self,co,t):
712       """
713            Cette methode a pour fonction de typer le concept co avec le type t
714             dans les conditions suivantes
715             1- co est un concept produit de self
716             2- co est un concept libre : on le type et on l attribue à self
717            Elle enregistre egalement les concepts produits (on fait l hypothese
718             que la liste sdprods a été correctement initialisee, vide probablement)
719       """
720       #print "type_sdprod",co,t
721       if not hasattr(co,'etape'):
722          # Le concept vaut None probablement. On ignore l'appel
723          return
724       #
725       # On cherche a discriminer les differents cas de typage d'un concept
726       # produit par une macro qui est specifie dans un mot cle simple.
727       # On peut passer plusieurs fois par type_sdprod ce qui explique
728       # le nombre important de cas.
729       #
730       # Cas 1 : Le concept est libre. Il vient d'etre cree par CO(nom)
731       # Cas 2 : Le concept est produit par la macro. On est deja passe par type_sdprod.
732       #         Cas semblable a Cas 1.
733       # Cas 3 : Le concept est produit par la macro englobante (parent). On transfere
734       #         la propriete du concept de la macro parent a la macro courante (self)
735       #         en verifiant que le type est valide
736       # Cas 4 : La concept est la propriete d'une etape fille. Ceci veut dire qu'on est
737       #         deja passe par type_sdprod et que la propriete a ete transfere a une
738       #         etape fille. Cas semblable a Cas 3.
739       # Cas 5 : Le concept est produit par une etape externe a la macro.
740       #
741       if co.etape == None:
742          # Cas 1 : le concept est libre
743          # On l'attache a la macro et on change son type dans le type demande
744          # Recherche du mot cle simple associe au concept
745          mcs=self.get_mcs_with_co(co)
746          if len(mcs) != 1:
747             raise AsException("""Erreur interne.
748 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
749          mcs=mcs[0]
750          #
751          # Attention : la seule modif est ici : Accas.CO au lieu de CO
752          #
753          if not Accas.CO in mcs.definition.type:
754             raise AsException("""Erreur interne.
755 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type))
756          co.etape=self
757          co.__class__ = t
758          self.sdprods.append(co)
759
760       elif co.etape== self:
761          # Cas 2 : le concept est produit par la macro (self)
762          # On est deja passe par type_sdprod (Cas 1 ou 3).
763          # Il suffit de le mettre dans la liste des concepts produits (self.sdprods)
764          # Le type du concept doit etre coherent avec le type demande (seulement derive)
765          if not isinstance(co,t):
766             raise AsException("""Erreur interne.
767 Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__))
768          self.sdprods.append(co)
769
770       elif co.etape== self.parent:
771          # Cas 3 : le concept est produit par la macro parente (self.parent)
772          # on transfere la propriete du concept a la macro fille
773          # et on change le type du concept comme demande
774          # Au prealable, on verifie que le concept existant (co) est une instance
775          # possible du type demande (t)
776          # Cette règle est normalement cohérente avec les règles de vérification des mots-clés
777          if not isinstance(co,t):
778             raise AsException("""
779 Impossible de changer le type du concept produit (%s) en (%s).
780 Le type actuel (%s) devrait etre une classe derivee du nouveau type (%s)""" % (co,t,co.__class__,t))
781          mcs=self.get_mcs_with_co(co)
782          if len(mcs) != 1:
783             raise AsException("""Erreur interne.
784 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
785          mcs=mcs[0]
786          if not Accas.CO in mcs.definition.type:
787             raise AsException("""Erreur interne.
788 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type))
789          co.etape=self
790          # On ne change pas le type car il respecte la condition isinstance(co,t)
791          #co.__class__ = t
792          self.sdprods.append(co)
793
794       elif self.issubstep(co.etape):
795          # Cas 4 : Le concept est propriété d'une sous etape de la macro (self).
796          # On est deja passe par type_sdprod (Cas 3 ou 1).
797          # Il suffit de le mettre dans la liste des concepts produits (self.sdprods)
798          # Le type du concept et t doivent etre derives.
799          # Il n'y a aucune raison pour que la condition ne soit pas verifiee.
800          if not isinstance(co,t):
801             raise AsException("""Erreur interne.
802 Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__))
803          self.sdprods.append(co)
804
805       else:
806          # Cas 5 : le concept est produit par une autre étape
807          # On ne fait rien
808          return
809