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