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