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