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.
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.
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.
20 # ======================================================================
25 import traceback,types,string
29 from Noyau.N_ASSD import ASSD
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 # fin import à résorber
37 class MACRO_ETAPE(I_ETAPE.ETAPE):
41 self.recorded_units={}
43 def get_sdprods(self,nom_sd):
45 Fonction : retourne le concept produit par l etape de nom nom_sd
46 s il existe sinon None
48 if self.sd and self.sd.nom == nom_sd :return self.sd
49 for co in self.sdprods:
50 if co.nom == nom_sd:return co
51 if type(self.definition.op_init) == types.FunctionType:
53 apply(self.definition.op_init,(self,d))
54 return d.get(nom_sd,None)
57 def get_contexte_jdc(self,fichier,text):
59 Interprète text comme un texte de jdc et retourne le
61 cad le dictionnaire des sd disponibles à la dernière étape
62 Si text n'est pas un texte de jdc valide, retourne None
64 --> utilisée par ops.POURSUITE et INCLUDE
67 # on essaie de créer un objet JDC auxiliaire avec un contexte initial
68 context_ini = self.parent.get_contexte_avant(self)
70 # Indispensable avant de creer un nouveau JDC
71 CONTEXT.unset_current_step()
74 if hasattr(self,'prefix'):
75 prefix_include=self.prefix
76 # ATTENTION : le dictionnaire recorded_units sert à memoriser les unites des
77 # fichiers inclus. Il est preferable de garder le meme dictionnaire pendant
78 # tout le traitement et de ne pas le reinitialiser brutalement (utiliser
79 # clear plutot) si on ne veut pas perdre la memoire des unites.
80 # En principe si la memorisation est faite au bon moment il n'est pas necessaire
81 # de prendre cette precaution mais ce n'est pas vrai partout.
82 old_recorded_units=self.recorded_units.copy()
83 self.recorded_units.clear()
85 j=self.JdC_aux( procedure=text,cata=self.jdc.cata,
87 context_ini = context_ini,
89 jdc_pere=self.jdc,etape_include=self,
90 prefix_include=prefix_include,
91 recorded_units=self.recorded_units,
92 old_recorded_units=old_recorded_units,**args)
95 # On récupère les étapes internes (pour validation)
99 # On force le contexte (etape courante) à self
100 CONTEXT.unset_current_step()
101 CONTEXT.set_current_step(self)
104 if not j.cr.estvide():
105 # Erreurs dans l'INCLUDE. On garde la memoire du fichier
106 # mais on n'insere pas les concepts
107 # On force le contexte (etape courante) à self
108 CONTEXT.unset_current_step()
109 CONTEXT.set_current_step(self)
110 raise Exception("Impossible de relire le fichier\n"+str(j.cr))
114 # L'INCLUDE n'est pas valide.
115 # On force le contexte (etape courante) à self
116 CONTEXT.unset_current_step()
117 CONTEXT.set_current_step(self)
118 raise Exception("Le fichier include contient des erreurs\n"+str(j.cr))
120 # On recupere le contexte de l'include verifie
122 j_context=j.get_verif_contexte()
124 CONTEXT.unset_current_step()
125 CONTEXT.set_current_step(self)
128 # On remplit le dictionnaire des concepts produits inclus
129 # en retirant les concepts présents dans le contexte initial
130 # On ajoute egalement le concept produit dans le sds_dict du parent
131 # sans verification car on est sur (verification integrée) que
132 # le nommage est possible
133 self.g_context.clear()
134 for k,v in j_context.items():
135 if not context_ini.has_key(k) or context_ini[k] != v:
137 self.parent.sds_dict[k]=v
140 # On recupere le contexte courant
141 self.current_context=j.current_context
142 self.index_etape_courante=j.index_etape_courante
144 # XXX j.supprime() ???
145 # On rétablit le contexte (etape courante) à self
146 CONTEXT.unset_current_step()
147 CONTEXT.set_current_step(self)
151 def reevalue_sd_jdc(self):
153 Avec la liste des SD qui ont été supprimées, propage la
154 disparition de ces SD dans toutes les étapes et descendants
156 l_sd_supp,l_sd_repl = self.diff_contextes()
158 self.parent.delete_concept_after_etape(self,sd)
159 for old_sd,sd in l_sd_repl:
160 self.parent.replace_concept_after_etape(self,old_sd,sd)
162 def diff_contextes(self):
164 Réalise la différence entre les 2 contextes
165 old_contexte_fichier_init et contexte_fichier_init
166 cad retourne la liste des sd qui ont disparu ou ne derivent pas
167 de la meme classe et des sd qui ont ete remplacees
169 if not hasattr(self,'old_contexte_fichier_init'):return [],[]
172 for old_key in self.old_contexte_fichier_init.keys():
173 if not self.contexte_fichier_init.has_key(old_key):
174 if isinstance(self.old_contexte_fichier_init[old_key],ASSD):
175 l_sd_suppressed.append(self.old_contexte_fichier_init[old_key])
177 if isinstance(self.old_contexte_fichier_init[old_key],ASSD):
178 # Un concept de meme nom existe
179 old_class=self.old_contexte_fichier_init[old_key].__class__
180 if not isinstance(self.contexte_fichier_init[old_key],old_class):
181 # S'il n'est pas d'une classe derivee, on le supprime
182 l_sd_suppressed.append(self.old_contexte_fichier_init[old_key])
184 l_sd_replaced.append((self.old_contexte_fichier_init[old_key],self.contexte_fichier_init[old_key]))
185 return l_sd_suppressed,l_sd_replaced
187 def control_sdprods(self,d):
189 Cette methode doit updater le contexte fournit par
190 l'appelant en argument (d) en fonction de sa definition
191 tout en verifiant que ses concepts produits ne sont pas
192 deja definis dans le contexte
194 if hasattr(self,"fichier_unite"):
195 self.update_fichier_init(self.fichier_unite)
198 if type(self.definition.op_init) == types.FunctionType:
199 apply(self.definition.op_init,(self,d))
201 if d.has_key(self.sd.nom):
202 # Le concept est deja defini
203 if self.reuse and self.reuse is d[self.sd.nom]:
204 # Le concept est reutilise : situation normale
207 # Redefinition du concept, on l'annule
208 #XXX on pourrait simplement annuler son nom pour conserver les objets
209 # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
210 self.sd=self.reuse=self.sdnom=None
213 # Le concept n'est pas defini, on peut updater d
214 d[self.sd.nom]=self.sd
215 # On verifie les concepts a droite du signe =
216 for co in self.sdprods:
217 if d.has_key(co.nom) and co is not d[co.nom] :
218 self.delete_concept(co)
223 def supprime_sdprods(self):
226 Lors d'une destruction d'etape, detruit tous les concepts produits
227 Un opérateur n a qu un concept produit
228 Une procedure n'en a aucun
229 Une macro en a en général plus d'un
231 if not self.is_reentrant() :
232 # l'étape n'est pas réentrante
233 # le concept retourné par l'étape est à supprimer car il était
236 self.parent.del_sdprod(self.sd)
237 self.parent.delete_concept(self.sd)
238 # On détruit les concepts à droite du signe =
239 for co in self.sdprods:
240 self.parent.del_sdprod(co)
241 self.parent.delete_concept(co)
242 # Si la macro a des etapes et des concepts inclus, on les detruit
243 for nom_sd,co in self.g_context.items():
244 if not isinstance(co,ASSD):continue
245 self.parent.del_sdprod(co)
246 self.parent.delete_concept(co)
247 # On met g_context à blanc
250 def make_contexte_include(self,fichier,text):
252 Cette méthode sert à créer un contexte en interprétant un texte source
255 # on récupère le contexte d'un nouveau jdc dans lequel on interprete text
256 contexte = self.get_contexte_jdc(fichier,text)
257 if contexte == None :
258 raise Exception("Impossible de construire le jeu de commandes correspondant au fichier")
260 # Pour les macros de type include : INCLUDE, INCLUDE_MATERIAU et POURSUITE
261 # l'attribut g_context est un dictionnaire qui contient les concepts produits par inclusion
262 # l'attribut contexte_fichier_init est un dictionnaire qui contient les concepts produits
263 # en sortie de macro. g_context est obtenu en retirant de contexte_fichier_init les concepts
264 # existants en debut de macro contenus dans context_ini (dans get_contexte_jdc)
265 # g_context est utilisé pour avoir les concepts produits par la macro
266 # contexte_fichier_init est utilisé pour avoir les concepts supprimés par la macro
267 self.contexte_fichier_init = contexte
269 def reevalue_fichier_init(self):
270 """Recalcule les concepts produits par le fichier enregistre"""
271 old_context=self.contexte_fichier_init
273 self.make_contexte_include(self.fichier_ini ,self.fichier_text)
275 l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
276 self.fichier_err = string.join(l)
280 self.old_contexte_fichier_init=old_context
281 self.contexte_fichier_init={}
282 self.reevalue_sd_jdc()
285 # L'evaluation s'est bien passee
286 self.fichier_err = None
287 self.old_contexte_fichier_init=old_context
288 self.reevalue_sd_jdc()
290 def update_fichier_init(self,unite):
291 """Reevalue le fichier init sans demander (dans la mesure du possible) a l'utilisateur
292 les noms des fichiers
293 Ceci suppose que les relations entre unites et noms ont été memorisees préalablement
296 self.fichier_err=None
297 self.old_contexte_fichier_init=self.contexte_fichier_init
299 if unite != self.fichier_unite or not self.parent.recorded_units.has_key(unite):
300 # Changement d'unite ou Nouvelle unite
301 f,text=self.get_file(unite=unite,fic_origine=self.parent.nom)
305 self.fichier_text=text
306 self.recorded_units=units
307 if self.fichier_ini is None and self.jdc.appli:
308 self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
309 message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini")
311 # Meme unite existante
312 f,text,units=self.parent.recorded_units[unite]
314 self.fichier_text=text
315 self.recorded_units=units
317 if self.fichier_ini is None:
318 # Le fichier n'est pas défini
319 self.fichier_err="Le fichier associé n'est pas défini"
320 self.parent.change_unit(unite,self,self.fichier_unite)
322 self.contexte_fichier_init={}
323 self.parent.reset_context()
324 self.reevalue_sd_jdc()
328 self.make_contexte_include(self.fichier_ini,self.fichier_text)
329 # Les 3 attributs fichier_ini fichier_text recorded_units doivent etre corrects
330 # avant d'appeler change_unit
331 self.parent.change_unit(unite,self,self.fichier_unite)
333 # Erreurs lors de l'evaluation de text dans un JDC auxiliaire
334 l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
335 # On conserve la memoire du nouveau fichier
336 # mais on n'utilise pas les concepts crees par ce fichier
337 # on met l'etape en erreur : fichier_err=string.join(l)
338 self.fichier_err=string.join(l)
339 self.parent.change_unit(unite,self,self.fichier_unite)
341 self.contexte_fichier_init={}
343 # Le contexte du parent doit etre reinitialise car les concepts
344 # produits ont changé
345 self.parent.reset_context()
346 # Si des concepts ont disparu lors du changement de fichier, on
347 # demande leur suppression
348 self.reevalue_sd_jdc()
350 def record_unite(self):
351 if self.nom == "POURSUITE":
352 self.parent.record_unit(None,self)
354 if hasattr(self,'fichier_unite') :
355 self.parent.record_unit(self.fichier_unite,self)
357 def get_file_memo(self,unite=None,fic_origine=''):
358 """Retourne le nom du fichier et le source correspondant a l'unite unite
359 Initialise en plus recorded_units
362 if self.parent.old_recorded_units.has_key(unite):
363 f,text,units=self.parent.old_recorded_units[unite]
364 self.recorded_units=units
367 f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
370 self.recorded_units=units
371 if f is None and self.jdc.appli:
372 self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
373 message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini")
376 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
377 def get_file(self,unite=None,fic_origine=''):
378 """Retourne le nom du fichier et le source correspondant a l'unite unite
379 Initialise en plus recorded_units
383 f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
386 self.recorded_units=units
389 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
390 def make_include(self,unite=None):
392 Inclut un fichier dont l'unite logique est unite
393 Cette methode est appelee par la fonction sd_prod de la macro INCLUDE
394 Si l'INCLUDE est invalide, la methode doit produire une exception
395 Sinon on retourne None. Les concepts produits par l'INCLUDE sont
396 pris en compte par le JDC parent lors du calcul du contexte (appel de ???)
399 # On supprime l'attribut unite qui bloque l'evaluation du source de l'INCLUDE
400 # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini
402 # Si unite n'a pas de valeur, l'etape est forcement invalide. On peut retourner None
403 if not unite : return
405 if not hasattr(self,'fichier_ini') :
406 # Si le fichier n'est pas defini on le demande
407 f,text=self.get_file_memo(unite=unite,fic_origine=self.parent.nom)
408 # On memorise le fichier retourne
410 self.fichier_text = text
411 self.contexte_fichier_init={}
412 self.fichier_unite=unite
413 self.fichier_err=None
414 import Extensions.jdc_include
415 self.JdC_aux=Extensions.jdc_include.JdC_include
418 self.fichier_err="Le fichier INCLUDE n est pas defini"
419 self.parent.record_unit(unite,self)
420 raise Exception(self.fichier_err)
423 self.make_contexte_include(self.fichier_ini ,self.fichier_text)
424 self.parent.record_unit(unite,self)
426 l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
428 self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
429 message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
431 self.parent.record_unit(unite,self)
433 self.fichier_err = string.join(l)
434 self.contexte_fichier_init={}
438 # Si le fichier est deja defini on ne reevalue pas le fichier
439 # et on leve une exception si une erreur a été enregistrée
440 self.update_fichier_init(unite)
441 self.fichier_unite=unite
442 if self.fichier_err is not None: raise Exception(self.fichier_err)
445 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
446 def make_contexte(self,fichier,text):
448 Cette méthode sert à créer un contexte pour INCLUDE_MATERIAU
449 en interprétant un texte source Python
450 Elle est appelee par la fonction sd_prd d'INCLUDE_MATERIAU
452 # On supprime l'attribut mat qui bloque l'evaluation du source de l'INCLUDE_MATERIAU
453 # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini
454 if hasattr(self,'mat'):del self.mat
455 self.fichier_ini =fichier
456 self.fichier_unite =fichier
457 self.fichier_text=text
458 self.fichier_err=None
459 self.contexte_fichier_init={}
460 # On specifie la classe a utiliser pour le JDC auxiliaire
461 import Extensions.jdc_include
462 self.JdC_aux=Extensions.jdc_include.JdC_include
464 self.make_contexte_include(self.fichier_ini ,self.fichier_text)
465 self.parent.record_unit(self.fichier_unite,self)
467 l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
468 self.fichier_err = string.join(l)
469 self.parent.record_unit(self.fichier_unite,self)
471 self.contexte_fichier_init={}
474 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
475 def update_sdprod(self,cr='non'):
476 # Cette methode peut etre appelee dans EFICAS avec des mots cles de
477 # la commande modifies. Ceci peut conduire a la construction ou
478 # a la reconstruction d'etapes dans le cas d'INCLUDE ou d'INCLUDE_MATERIAU
479 # Il faut donc positionner le current_step avant l'appel
480 CONTEXT.unset_current_step()
481 CONTEXT.set_current_step(self)
482 valid=Validation.V_MACRO_ETAPE.MACRO_ETAPE.update_sdprod(self,cr=cr)
483 CONTEXT.unset_current_step()
486 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro
487 def Build_sd(self,nom):
489 Methode de Noyau surchargee pour poursuivre malgre tout
490 si une erreur se produit pendant la creation du concept produit
493 sd=Noyau.N_MACRO_ETAPE.MACRO_ETAPE.Build_sd(self,nom)
494 self.state="modified"
495 except AsException,e:
496 # Une erreur s'est produite lors de la construction du concept
497 # Comme on est dans EFICAS, on essaie de poursuivre quand meme
498 # Si on poursuit, on a le choix entre deux possibilités :
499 # 1. on annule la sd associée à self
500 # 2. on la conserve mais il faut la retourner
501 # On choisit de l'annuler
502 # En plus il faut rendre coherents sdnom et sd.nom
505 self.state="unchanged"
510 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro
511 def make_poursuite(self):
512 """ Cette methode est appelée par la fonction sd_prod de la macro POURSUITE
514 if not hasattr(self,'fichier_ini') :
515 # Si le fichier n'est pas defini on le demande
516 f,text=self.get_file_memo(fic_origine=self.parent.nom)
517 # On memorise le fichier retourne
519 self.fichier_unite = None
520 self.fichier_text = text
521 self.fichier_err=None
522 import Extensions.jdc_include
523 self.JdC_aux=Extensions.jdc_include.JdC_poursuite
524 self.contexte_fichier_init={}
527 self.fichier_err="Le fichier POURSUITE n'est pas defini"
528 self.parent.record_unit(None,self)
529 raise Exception(self.fichier_err)
532 self.make_contexte_include(self.fichier_ini,self.fichier_text)
533 self.parent.record_unit(None,self)
535 l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
537 self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier poursuite",
538 message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
540 self.parent.record_unit(None,self)
542 self.fichier_err = string.join(l)
543 self.contexte_fichier_init={}
547 # Si le fichier est deja defini on ne reevalue pas le fichier
548 # et on leve une exception si une erreur a été enregistrée
549 self.update_fichier_init(None)
550 if self.fichier_err is not None: raise Exception(self.fichier_err)