Salome HOME
mise a jour Noyau+Validation v8.0.16
[tools/eficas.git] / Noyau / N_MACRO_ETAPE.py
1 #@ MODIF N_MACRO_ETAPE Noyau  DATE 22/02/2005   AUTEUR DURAND C.DURAND 
2 # -*- coding: iso-8859-1 -*-
3 #            CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
6 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
7 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
8 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR   
9 # (AT YOUR OPTION) ANY LATER VERSION.                                 
10 #
11 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT 
12 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF          
13 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU    
14 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.                            
15 #
16 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE   
17 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,       
18 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.      
19 #                                                                       
20 #                                                                       
21 # ======================================================================
22
23
24 """ 
25     Ce module contient la classe MACRO_ETAPE qui sert à vérifier et à exécuter
26     une commande
27 """
28
29 # Modules Python
30 import types,sys,string
31 import traceback
32
33 # Modules EFICAS
34 import N_MCCOMPO
35 import N_ETAPE
36 from N_Exception import AsException
37 import N_utils
38 from N_utils import AsType
39 from N_CO import CO
40
41 class MACRO_ETAPE(N_ETAPE.ETAPE):
42    """
43
44    """
45    nature = "COMMANDE"
46    def __init__(self,oper=None,reuse=None,args={}):
47       """
48          Attributs :
49
50           - definition : objet portant les attributs de définition d'une étape 
51                          de type macro-commande. Il est initialisé par 
52                           l'argument oper.
53
54           - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc
55                     en sortie si les conditions d'exécution de l'opérateur 
56                     l'autorise
57
58           - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé 
59                      avec l'argument args.
60
61       """
62       self.definition=oper
63       self.reuse=reuse
64       self.valeur=args
65       self.nettoiargs()
66       self.parent=CONTEXT.get_current_step()
67       self.etape = self
68       self.nom=oper.nom
69       self.idracine=oper.label
70       self.appel=N_utils.callee_where()
71       self.mc_globaux={}
72       self.g_context={}
73       # Contexte courant
74       self.current_context={}
75       self.index_etape_courante=0
76       self.etapes=[]
77       self.sds=[]
78       #  Dans le cas d'une macro écrite en Python, l'attribut Outputs est un 
79       #  dictionnaire qui contient les concepts produits de sortie 
80       #  (nom : ASSD) déclarés dans la fonction sd_prod
81       self.Outputs={}
82       self.sd=None
83       self.actif=1
84       self.sdprods=[]
85       self.make_register()
86
87    def make_register(self):
88       """
89          Initialise les attributs jdc, id, niveau et réalise les enregistrements
90          nécessaires
91       """
92       if self.parent :
93          self.jdc = self.parent.get_jdc_root()
94          self.id=self.parent.register(self)
95          self.niveau=None
96          self.UserError=self.jdc.UserError
97       else:
98          self.jdc = self.parent =None
99          self.id=None
100          self.niveau=None
101          self.UserError="UserError"
102
103    def Build_sd(self,nom):
104       """
105          Construit le concept produit de l'opérateur. Deux cas 
106          peuvent se présenter :
107         
108          - le parent n'est pas défini. Dans ce cas, l'étape prend en charge 
109            la création et le nommage du concept.
110
111          - le parent est défini. Dans ce cas, l'étape demande au parent la 
112            création et le nommage du concept.
113
114       """
115       if not self.isactif():return
116       self.sdnom=nom
117       try:
118          # On positionne la macro self en tant que current_step pour que les 
119          # étapes créées lors de l'appel à sd_prod et à op_init aient la macro
120          #  comme parent 
121          self.set_current_step()
122          if self.parent:
123             sd= self.parent.create_sdprod(self,nom)
124             if type(self.definition.op_init) == types.FunctionType: 
125                apply(self.definition.op_init,(self,self.parent.g_context))
126          else:
127             sd=self.get_sd_prod()
128             if sd != None and self.reuse == None:
129                # On ne nomme le concept que dans le cas de non reutilisation 
130                # d un concept
131                sd.nom=nom
132          self.reset_current_step()
133       except AsException,e:
134          self.reset_current_step()
135          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
136                               'fichier : ',self.appel[1],e)
137       except (EOFError,self.UserError):
138          # Le retablissement du step courant n'est pas strictement necessaire. On le fait pour des raisons de coherence
139          self.reset_current_step()
140          raise
141       except :
142          self.reset_current_step()
143          l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
144          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
145                            'fichier : ',self.appel[1]+'\n',
146                             string.join(l))
147
148       self.Execute()
149       return sd
150
151    def mark_CO(self):
152       """
153          Marquage des concepts CO d'une macro-commande
154       """
155       # On marque les concepts CO pour verification ulterieure de leur bonne utilisation
156       l=self.get_all_co()
157       for c in l:
158           #if not hasattr(c,"_etape") or c._etape is not c.etape: 
159              c._etape=self
160       return l
161
162    def get_sd_prod(self):
163       """
164         Retourne le concept résultat d'une macro étape
165         La difference avec une etape ou une proc-etape tient a ce que
166          le concept produit peut exister ou pas
167         Si sd_prod == None le concept produit n existe pas on retourne None
168         Deux cas :
169          cas 1 : sd_prod  n'est pas une fonction
170                  il s'agit d'une sous classe de ASSD
171                  on construit le sd à partir de cette classe
172                  et on le retourne
173          cas 2 : sd_prod est une fonction
174                   on l'évalue avec les mots-clés de l'étape (mc_liste)
175                  on construit le sd à partir de la classe obtenue
176                  et on le retourne
177       """
178       sd_prod=self.definition.sd_prod
179       self.typret=None
180       # On marque les concepts CO pour verification ulterieure de leur bonne utilisation
181       self.mark_CO()
182
183       if type(self.definition.sd_prod) == types.FunctionType:
184         d=self.cree_dict_valeurs(self.mc_liste)
185         try:
186           # la sd_prod d'une macro a l'objet macro_etape lui meme en premier argument
187           # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute
188           # les concepts produits dans self.sdprods, il faut le mettre à zéro avant de l'appeler
189           self.sdprods=[]
190           sd_prod= apply(sd_prod,(self,),d)
191         except (EOFError,self.UserError):
192           raise
193         except:
194           if CONTEXT.debug: traceback.print_exc()
195           l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
196           raise AsException("impossible d affecter un type au resultat\n",string.join(l[2:]))
197
198       # on teste maintenant si la SD est réutilisée ou s'il faut la créer
199       if self.definition.reentrant != 'n' and self.reuse:
200         # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
201         # Elle sera traitee ulterieurement.
202         self.sd=self.reuse
203       else:
204         if sd_prod == None:
205           self.sd=None
206         else:
207           self.sd= sd_prod(etape=self)
208           self.typret=sd_prod
209           # Si la commande est obligatoirement reentrante et reuse n'a pas ete specifie, c'est une erreur. 
210           # On ne fait rien ici. L'erreur sera traitee par la suite. 
211       return self.sd
212
213    def get_type_produit(self,force=0):
214       try:
215           return self.get_type_produit_brut(force)
216       except:
217           #traceback.print_exc()
218           return None
219
220    def get_type_produit_brut(self,force=0):
221       """
222            Retourne le type du concept résultat de l'étape et eventuellement type
223             les concepts produits "à droite" du signe égal (en entrée)
224            Deux cas :
225             cas 1 : sd_prod de oper n'est pas une fonction
226                     il s'agit d'une sous classe de ASSD
227                     on retourne le nom de la classe
228             cas 2 : il s'agit d'une fonction
229                     on l'évalue avec les mots-clés de l'étape (mc_liste)
230                     et on retourne son résultat
231       """
232       if not force and hasattr(self,'typret'): return self.typret
233       # On marque les concepts CO pour verification ulterieure de leur bonne utilisation
234       self.mark_CO()
235
236       if type(self.definition.sd_prod) == types.FunctionType:
237         d=self.cree_dict_valeurs(self.mc_liste)
238         # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute
239         # les concepts produits dans self.sdprods, il faut le mettre à zéro
240         self.sdprods=[]
241         sd_prod= apply(self.definition.sd_prod,(self,),d)
242       else:
243         sd_prod=self.definition.sd_prod
244       return sd_prod
245
246    def get_contexte_avant(self,etape):
247       """
248           Retourne le dictionnaire des concepts connus avant etape
249           pour les commandes internes a la macro
250           On tient compte des commandes qui modifient le contexte
251           comme DETRUIRE ou les macros
252       """
253       # L'étape courante pour laquelle le contexte a été calculé est 
254       # mémorisée dans self.index_etape_courante
255       # Si on insère des commandes (par ex, dans EFICAS), il faut
256       # préalablement remettre ce pointeur à 0
257       if etape:
258          index_etape=self.etapes.index(etape)
259       else:
260          index_etape=len(self.etapes)
261
262       if index_etape >= self.index_etape_courante:
263          # On calcule le contexte en partant du contexte existant
264          d=self.current_context
265          liste_etapes=self.etapes[self.index_etape_courante:index_etape]
266       else:
267          d=self.current_context={}
268          liste_etapes=self.etapes
269
270       for e in liste_etapes:
271         if e is etape:
272            break
273         if e.isactif():
274            e.update_context(d)
275       self.index_etape_courante=index_etape
276       return d
277
278    def supprime(self):
279       """
280          Méthode qui supprime toutes les références arrières afin que 
281          l'objet puisse etre correctement détruit par le garbage collector
282       """
283       N_MCCOMPO.MCCOMPO.supprime(self)
284       self.jdc=None
285       self.appel=None
286       if self.sd : self.sd.supprime()
287       for concept in self.sdprods:
288          concept.supprime()
289       for etape in self.etapes:
290          etape.supprime()
291
292    def type_sdprod(self,co,t):
293       """
294            Cette methode a pour fonction de typer le concept co avec le type t
295             dans les conditions suivantes
296             1- co est un concept produit de self
297             2- co est un concept libre : on le type et on l attribue à self
298            Elle enregistre egalement les concepts produits (on fait l hypothese
299             que la liste sdprods a été correctement initialisee, vide probablement)
300       """
301       if not hasattr(co,'etape'):
302          # Le concept vaut None probablement. On ignore l'appel
303          return
304       # 
305       # On cherche a discriminer les differents cas de typage d'un concept
306       # produit par une macro qui est specifie dans un mot cle simple.
307       # On peut passer plusieurs fois par type_sdprod ce qui explique
308       # le nombre important de cas.
309       #
310       # Cas 1 : Le concept est libre. Il vient d'etre cree par CO(nom)
311       # Cas 2 : Le concept est produit par la macro. On est deja passe par type_sdprod.
312       #         Cas semblable a Cas 1.
313       # Cas 3 : Le concept est produit par la macro englobante (parent). On transfere
314       #         la propriete du concept de la macro parent a la macro courante (self)
315       #         en verifiant que le type est valide
316       # Cas 4 : La concept est la propriete d'une etape fille. Ceci veut dire qu'on est
317       #         deja passe par type_sdprod et que la propriete a ete transfere a une 
318       #         etape fille. Cas semblable a Cas 3.
319       # Cas 5 : Le concept est produit par une etape externe a la macro.
320       #
321       if co.etape == None:
322          # Cas 1 : le concept est libre
323          # On l'attache a la macro et on change son type dans le type demande
324          # Recherche du mot cle simple associe au concept
325          mcs=self.get_mcs_with_co(co)
326          if len(mcs) != 1:
327             raise AsException("""Erreur interne. 
328 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
329          mcs=mcs[0]
330          if not CO in mcs.definition.type:
331             raise AsException("""Erreur interne. 
332 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type))
333          co.etape=self
334          co.__class__ = t
335          self.sdprods.append(co)
336
337       elif co.etape== self:
338          # Cas 2 : le concept est produit par la macro (self)
339          # On est deja passe par type_sdprod (Cas 1 ou 3).
340          # Il suffit de le mettre dans la liste des concepts produits (self.sdprods)
341          # Le type du concept doit etre coherent avec le type demande (seulement derive)
342          if not isinstance(co,t):
343             raise AsException("""Erreur interne. 
344 Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__))
345          self.sdprods.append(co)
346
347       elif co.etape== self.parent:
348          # Cas 3 : le concept est produit par la macro parente (self.parent)
349          # on transfere la propriete du concept a la macro fille
350          # et on change le type du concept comme demande
351          # Au prealable, on verifie que le concept existant (co) est une instance 
352          # possible du type demande (t)
353          # Cette règle est normalement cohérente avec les règles de vérification des mots-clés
354          if not isinstance(co,t):
355             raise AsException("""
356 Impossible de changer le type du concept produit (%s) en (%s).
357 Le type actuel (%s) devrait etre une classe derivee du nouveau type (%s)""" % (co,t,co.__class__,t))
358          mcs=self.get_mcs_with_co(co)
359          if len(mcs) != 1:
360             raise AsException("""Erreur interne. 
361 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
362          mcs=mcs[0]
363          if not CO in mcs.definition.type:
364             raise AsException("""Erreur interne. 
365 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type))
366          co.etape=self
367          # On ne change pas le type car il respecte la condition isinstance(co,t)
368          #co.__class__ = t
369          self.sdprods.append(co)
370
371       elif self.issubstep(co.etape):
372          # Cas 4 : Le concept est propriété d'une sous etape de la macro (self). 
373          # On est deja passe par type_sdprod (Cas 3 ou 1).
374          # Il suffit de le mettre dans la liste des concepts produits (self.sdprods)
375          # Le type du concept et t doivent etre derives. 
376          # Il n'y a aucune raison pour que la condition ne soit pas verifiee.
377          if not isinstance(co,t):
378             raise AsException("""Erreur interne. 
379 Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__))
380          self.sdprods.append(co)
381
382       else:
383          # Cas 5 : le concept est produit par une autre étape
384          # On ne fait rien
385          return
386
387    def issubstep(self,etape):
388       """ 
389           Cette methode retourne un entier indiquant si etape est une
390           sous etape de la macro self ou non
391           1 = oui
392           0 = non
393       """
394       if etape in self.etapes:return 1
395       for etap in self.etapes:
396         if etap.issubstep(etape):return 1
397       return 0
398
399    def register(self,etape):
400       """ 
401           Enregistrement de etape dans le contexte de la macro : liste etapes 
402           et demande d enregistrement global aupres du JDC
403       """
404       self.etapes.append(etape)
405       idetape=self.jdc.g_register(etape)
406       return idetape
407
408    def reg_sd(self,sd):
409       """ 
410            Methode appelee dans l __init__ d un ASSD a sa creation pour
411            s enregistrer (reserve aux ASSD créés au sein d'une MACRO)
412       """
413       self.sds.append(sd)
414       return self.jdc.o_register(sd)
415
416    def create_sdprod(self,etape,nomsd):
417       """ 
418           Intention : Cette methode doit fabriquer le concept produit retourne
419                   par l'etape etape et le nommer.
420                   Elle est appelée à l'initiative de l'etape
421                   pendant le processus de construction de cette etape : methode __call__
422                   de la classe CMD (OPER ou MACRO)
423                   Ce travail est réalisé par le contexte supérieur (etape.parent)
424                   car dans certains cas, le concept ne doit pas etre fabriqué mais
425                   l'etape doit simplement utiliser un concept préexistant.
426                   Cas 1 : etape.reuse != None : le concept est réutilisé
427                   Cas 2 : l'étape appartient à une macro qui a déclaré un concept
428                           de sortie qui doit etre produit par cette etape.
429       """
430       if self.Outputs.has_key(nomsd):
431          # Il s'agit d'un concept de sortie de la macro. Il ne faut pas le créer
432          # Il faut quand meme appeler la fonction sd_prod si elle existe.
433          # get_type_produit le fait et donne le type attendu par la commande pour verification ultérieure.
434          sdprod=etape.get_type_produit_brut()
435          sd=self.Outputs[nomsd]
436          # On verifie que le type du concept existant sd.__class__ est un sur type de celui attendu
437          # Cette règle est normalement cohérente avec les règles de vérification des mots-clés
438          if not issubclass(sdprod,sd.__class__):
439             raise AsException("Le type du concept produit %s devrait etre une sur classe de %s" %(sd.__class__,sdprod))
440          # La propriete du concept est transferee a l'etape avec le type attendu par l'étape
441          etape.sd=sd
442          sd.etape=etape
443          # On donne au concept le type produit par la sous commande.
444          # Le principe est le suivant : apres avoir verifie que le type deduit par la sous commande
445          # est bien coherent avec celui initialement affecte par la macro (voir ci dessus)
446          # on affecte au concept ce type car il peut etre plus precis (derive, en general)
447          sd.__class__=sdprod
448          # On force également le nom stocké dans l'attribut sdnom : on lui donne le nom 
449          # du concept associé à nomsd
450          etape.sdnom=sd.nom
451       elif etape.definition.reentrant != 'n' and etape.reuse != None:
452          # On est dans le cas d'une commande avec reutilisation d'un concept existant
453          # get_sd_prod fait le necessaire : verifications, associations, etc. mais ne cree 
454          # pas un nouveau concept. Il retourne le concept reutilise
455          sd= etape.get_sd_prod()
456          # Dans le cas d'un concept nomme automatiquement : _xxx, __xxx,
457          # On force le nom stocke dans l'attribut sdnom  de l'objet etape : on lui donne le nom 
458          # du concept  reutilise (sd ou etape.reuse c'est pareil)
459          # Ceci est indispensable pour eviter des erreurs lors des verifications des macros
460          # En effet une commande avec reutilisation d'un concept verifie que le nom de 
461          # la variable a gauche du signe = est le meme que celui du concept reutilise.
462          # Lorsqu'une telle commande apparait dans une macro, on supprime cette verification.
463          if (etape.sdnom == '' or etape.sdnom[0] == '_'):
464             etape.sdnom=sd.nom
465       else:
466          # On est dans le cas de la creation d'un nouveau concept
467          sd= etape.get_sd_prod()
468          if sd != None :
469             self.NommerSdprod(sd,nomsd)
470       return sd
471
472    def NommerSdprod(self,sd,sdnom,restrict='non'):
473       """ 
474           Cette methode est appelee par les etapes internes de la macro
475           La macro appelle le JDC pour valider le nommage
476           On considere que l espace de nom est unique et géré par le JDC
477           Si le nom est deja utilise, l appel leve une exception
478           Si restrict=='non', on insere le concept dans le contexte de la macro
479           Si restrict=='oui', on n'insere pas le concept dans le contexte de la macro
480       """
481       # Normalement, lorsqu'on appelle cette methode, on ne veut nommer que des concepts nouvellement crees.
482       # Le filtrage sur les concepts a creer ou a ne pas creer est fait dans la methode
483       # create_sdprod. La seule chose a verifier apres conversion eventuelle du nom
484       # est de verifier que le nom n'est pas deja attribue. Ceci est fait en delegant
485       # au JDC par l'intermediaire du parent.
486
487       #XXX attention inconsistence : prefix et gcncon ne sont pas 
488       # définis dans le package Noyau. La methode NommerSdprod pour
489       # les macros devrait peut etre etre déplacée dans Build ???
490
491       if CONTEXT.debug : print "MACRO.NommerSdprod: ",sd,sdnom
492
493       if hasattr(self,'prefix'):
494         # Dans le cas de l'include_materiau on ajoute un prefixe au nom du concept
495         if sdnom != self.prefix:sdnom=self.prefix+sdnom
496
497       if self.Outputs.has_key(sdnom):
498         # Il s'agit d'un concept de sortie de la macro produit par une sous commande
499         sdnom=self.Outputs[sdnom].nom
500       elif sdnom != '' and sdnom[0] == '_':
501         # Si le nom du concept commence par le caractere _ on lui attribue
502         # un identificateur JEVEUX construit par gcncon et respectant
503         # la regle gcncon legerement adaptee ici
504         # nom commencant par __ : il s'agit de concepts qui seront detruits
505         # nom commencant par _ : il s'agit de concepts intermediaires qui seront gardes
506         # ATTENTION : il faut traiter différemment les concepts dont le nom
507         # commence par _ mais qui sont des concepts nommés automatiquement par
508         # une éventuelle sous macro.
509         # Le test suivant n'est pas tres rigoureux mais permet de fonctionner pour le moment (a améliorer)
510         if sdnom[1] in string.digits:
511           # Ce concept provient probablement d'une macro appelee par self
512           pass
513         elif sdnom[1] == '_':
514           sdnom=self.gcncon('.')
515         else:
516           sdnom=self.gcncon('_')
517       else:
518         # On est dans le cas d'un nom de concept global. 
519         pass
520
521       if restrict == 'non':
522          # On demande le nommage au parent mais sans ajout du concept dans le contexte du parent
523          # car on va l'ajouter dans le contexte de la macro
524          self.parent.NommerSdprod(sd,sdnom,restrict='oui')
525          # On ajoute dans le contexte de la macro les concepts nommes
526          # Ceci est indispensable pour les CO (macro) dans un INCLUDE
527          self.g_context[sdnom]=sd
528       else:
529          # La demande de nommage vient probablement d'une macro qui a mis
530          # le concept dans son contexte. On ne traite plus que le nommage (restrict="oui")
531          self.parent.NommerSdprod(sd,sdnom,restrict='oui')
532
533    def delete_concept_after_etape(self,etape,sd):
534       """
535           Met à jour les étapes de la MACRO  qui sont après etape suite à
536           la disparition du concept sd
537       """
538       # Cette methode est définie dans le noyau mais ne sert que pendant la phase de creation
539       # des etapes et des concepts. Il n'y a aucun traitement particulier à réaliser
540       # Dans d'autres conditions, il faudrait surcharger cette méthode.
541       return
542
543    def accept(self,visitor):
544       """
545          Cette methode permet de parcourir l'arborescence des objets
546          en utilisant le pattern VISITEUR
547       """
548       visitor.visitMACRO_ETAPE(self)
549
550    def update_context(self,d):
551       """
552          Met à jour le contexte contenu dans le dictionnaire d
553          Une MACRO_ETAPE peut ajouter plusieurs concepts dans le contexte
554          Une fonction enregistree dans op_init peut egalement modifier le contexte
555       """
556       if type(self.definition.op_init) == types.FunctionType:
557         apply(self.definition.op_init,(self,d))
558       if self.sd != None:d[self.sd.nom]=self.sd
559       for co in self.sdprods:
560         d[co.nom]=co
561
562    def make_include(self,unite=None):
563       """
564           Inclut un fichier dont l'unite logique est unite
565       """
566       if not unite : return
567       f,text=self.get_file(unite=unite,fic_origine=self.parent.nom)
568       self.fichier_init = f
569       if f == None:return
570       self.make_contexte(f,text)
571
572    def make_poursuite(self):
573       """
574           Inclut un fichier poursuite
575       """
576       try:
577          f,text=self.get_file(fic_origine=self.parent.nom)
578       except:
579          raise AsException("Impossible d'ouvrir la base pour une poursuite")
580       self.fichier_init=f
581       if f == None:return
582       self.make_contexte(f,text)
583
584    def make_contexte(self,f,text):
585       """
586           Interprete le texte fourni (text) issu du fichier f
587           dans le contexte du parent.
588           Cette methode est utile pour le fonctionnement des
589           INCLUDE
590       """
591       # on execute le texte fourni dans le contexte forme par
592       # le contexte de l etape pere (global au sens Python)
593       # et le contexte de l etape (local au sens Python)
594       code=compile(text,f,'exec')
595       d={}
596       self.g_context = d
597       self.contexte_fichier_init = d
598       globs=self.parent.get_global_contexte()
599       exec code in globs,d
600
601    def get_global_contexte(self):
602       """
603           Cette methode retourne le contexte global fourni
604           par le parent(self) a une etape fille (l'appelant) pour
605           realiser des evaluations de texte Python (INCLUDE,...)
606       """
607       # Le contexte global est forme par concatenation du contexte
608       # du parent de self et de celui de l'etape elle meme (self)
609       d=self.parent.get_global_contexte()
610       d.update(self.g_context)
611       return d
612
613    def copy(self):
614       """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
615           et sans sd
616           On surcharge la methode de ETAPE pour exprimer que les concepts crees
617           par la MACRO d'origine ne sont pas crees par la copie mais eventuellement
618           seulement utilises
619       """
620       etape=N_ETAPE.ETAPE.copy(self)
621       etape.sdprods=[]
622       return etape
623
624    def copy_intern(self,etape):
625       """ Cette méthode effectue la recopie des etapes internes d'une macro 
626           passée en argument (etape)
627       """
628       self.etapes=[]
629       for etp in etape.etapes:
630           new_etp=etp.copy()
631           new_etp.copy_reuse(etp)
632           new_etp.copy_sdnom(etp)
633           new_etp.reparent(self)
634           if etp.sd:
635              new_sd = etp.sd.__class__(etape=new_etp)
636              new_etp.sd = new_sd
637              if etp.reuse:
638                 new_sd.nom = etp.sd.nom
639              else:
640                 self.NommerSdprod(new_sd,etp.sd.nom)
641           new_etp.copy_intern(etp)
642           self.etapes.append(new_etp)
643
644
645
646
647
648
649