Salome HOME
CCAR:amelioration de la fonctionnalité mots clés inconnus
[tools/eficas.git] / Noyau / N_ETAPE.py
1 """ 
2     Ce module contient la classe ETAPE qui sert à vérifier et à exécuter
3     une commande
4 """
5
6 # Modules Python
7 import types,sys,string,os
8 import linecache
9 import traceback
10
11 # Modules EFICAS
12 import N_MCCOMPO
13 from N_Exception import AsException
14 import N_utils
15 from N_utils import AsType
16
17 class ETAPE(N_MCCOMPO.MCCOMPO):
18    """
19       Cette classe hérite de MCCOMPO car ETAPE est un OBJECT composite
20
21    """
22    nature = "OPERATEUR"
23
24    # L'attribut de classe codex est utilisé pour rattacher le module de calcul éventuel (voir Build)
25    # On le met à None pour indiquer qu'il n'y a pas de module de calcul rattaché
26    codex=None
27
28    def __init__(self,oper=None,reuse=None,args={}):
29       """
30          Attributs :
31
32           - definition : objet portant les attributs de définition d'une étape de type opérateur. Il
33                          est initialisé par l'argument oper.
34
35           - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc en sortie
36                     si les conditions d'exécution de l'opérateur l'autorise
37
38           - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé avec l'argument args.
39
40       """
41       self.definition=oper
42       self.reuse=reuse
43       self.valeur=args
44       self.nettoiargs()
45       self.parent=CONTEXT.get_current_step()
46       self.etape = self
47       self.nom=oper.nom
48       self.idracine=oper.label
49       self.appel=N_utils.callee_where()
50       self.mc_globaux={}
51       self.sd=None
52       self.actif=1
53       self.make_register()
54
55    def make_register(self):
56       """
57          Initialise les attributs jdc, id, niveau et réalise les 
58          enregistrements nécessaires
59       """
60       if self.parent :
61          self.jdc = self.parent.get_jdc_root()
62          self.id=self.parent.register(self)
63          self.niveau=None
64       else:
65          self.jdc = self.parent =None
66          self.id=None
67          self.niveau=None
68
69    def nettoiargs(self):
70       """
71          Cette methode a pour fonction de retirer tous les arguments egaux à None
72          de la liste des arguments. Ils sont supposés non présents et donc retirés.
73       """
74       for k in self.valeur.keys():
75          if self.valeur[k] == None:del self.valeur[k]
76
77    def McBuild(self):
78       """
79          Demande la construction des sous-objets et les stocke dans l'attribut
80          mc_liste.
81       """
82       self.mc_liste=self.build_mc()
83
84    def Build_sd(self,nom):
85       """
86          Construit le concept produit de l'opérateur. Deux cas 
87          peuvent se présenter :
88         
89          - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création 
90            et le nommage du concept.
91
92          - le parent est défini. Dans ce cas, l'étape demande au parent la création et 
93            le nommage du concept.
94
95       """
96       if not self.isactif():return
97       try:
98          if self.parent:
99             sd= self.parent.create_sdprod(self,nom)
100             if type(self.definition.op_init) == types.FunctionType: 
101                apply(self.definition.op_init,(self,self.parent.g_context))
102          else:
103             sd=self.get_sd_prod()
104             # On n'utilise pas self.definition.op_init car self.parent 
105             # n'existe pas
106             if sd != None and self.reuse == None:
107                # On ne nomme le concept que dans le cas de non reutilisation 
108                # d un concept
109                sd.nom=nom
110          if self.jdc and self.jdc.par_lot == "NON" :
111             self.Execute()
112          return sd
113       except AsException,e:
114          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
115                               'fichier : ',self.appel[1],e)
116       except EOFError:
117          # XXX Normalement le contexte courant doit etre le parent.
118          # Il n'y a pas de raison de remettre le contexte au parent
119          #self.reset_current_step()
120          raise
121       except :
122          l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
123          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
124                            'fichier : ',self.appel[1]+'\n',
125                             string.join(l))
126
127    def Execute(self):
128       """
129          Cette methode est prevue pour faire une execution dans le cas
130          ou par_lot == 'NON'
131          Par defaut, elle ne fait rien
132       """
133       return
134
135    def get_sd_prod(self):
136       """
137           Retourne le concept résultat de l'étape
138           Deux cas :
139                    cas 1 : sd_prod de oper n'est pas une fonction
140                            il s'agit d'une sous classe de ASSD
141                            on construit le sd à partir de cette classe
142                            et on le retourne
143                    cas 2 : il s'agit d'une fonction
144                            on l'évalue avec les mots-clés de l'étape (mc_liste)
145                            on construit le sd à partir de la classe obtenue
146                            et on le retourne
147       """
148       if type(self.definition.sd_prod) == types.FunctionType:
149         d=self.cree_dict_valeurs(self.mc_liste)
150         try:
151           sd_prod= apply(self.definition.sd_prod,(),d)
152         except EOFError:
153           raise
154         except:
155           if CONTEXT.debug: traceback.print_exc()
156           l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
157                                        sys.exc_info()[2])
158           raise AsException("impossible d affecter un type au resultat",
159                              string.join(l[2:]))
160           #         sys.exc_info()[0],sys.exc_info()[1],)
161       else:
162         sd_prod=self.definition.sd_prod
163       # on teste maintenant si la SD est réutilisée ou s'il faut la créer
164       if self.reuse:
165         if AsType(self.reuse) != sd_prod:
166           raise AsException("type de concept reutilise incompatible avec type produit")
167         self.sd=self.reuse
168       else:
169         self.sd= sd_prod(etape=self)
170         if self.definition.reentrant == 'o':
171           self.reuse = self.sd
172       return self.sd
173
174    def get_type_produit(self):
175       """
176           Retourne le type du concept résultat de l'étape
177           Deux cas :
178            cas 1 : sd_prod de oper n'est pas une fonction
179                    il s'agit d'une sous classe de ASSD
180                    on retourne le nom de la classe
181            cas 2 : il s'agit d'une fonction
182                     on l'évalue avec les mots-clés de l'étape (mc_liste)
183                    et on retourne son résultat
184       """
185       if type(self.definition.sd_prod) == types.FunctionType:
186         d=self.cree_dict_valeurs(self.mc_liste)
187         try:
188           sd_prod= apply(self.definition.sd_prod,(),d)
189         except:
190           #traceback.print_exc()
191           return None
192       else:
193         sd_prod=self.definition.sd_prod
194       return sd_prod
195
196    def get_etape(self):
197       """
198          Retourne l'étape à laquelle appartient self
199          Un objet de la catégorie etape doit retourner self pour indiquer que
200          l'étape a été trouvée
201          XXX fait double emploi avec self.etape ????
202       """
203       return self
204
205    def supprime(self):
206       """
207          Méthode qui supprime toutes les références arrières afin que l'objet puisse
208          être correctement détruit par le garbage collector
209       """
210       N_MCCOMPO.MCCOMPO.supprime(self)
211       self.jdc=None
212       self.appel=None
213       if self.sd : self.sd.supprime()
214
215    def isactif(self):
216       """ 
217          Indique si l'étape est active (1) ou inactive (0)
218       """
219       return self.actif
220
221    def set_current_step(self):
222       """
223           Methode utilisee pour que l etape self se declare etape
224           courante. Utilise par les macros
225       """
226       #print "set_current_step ",self.nom
227       #traceback.print_stack(limit=3,file=sys.stdout)
228       cs= CONTEXT.get_current_step()
229       if self.parent != cs :
230          raise "L'étape courante %s devrait etre le parent de self : %s" % (cs,self)
231       else :
232          CONTEXT.unset_current_step()
233          CONTEXT.set_current_step(self)
234
235    def reset_current_step(self):
236       """ 
237             Methode utilisee par l'etape self qui remet son etape parent comme 
238              etape courante 
239       """
240       #print "reset_current_step ",self.nom
241       #traceback.print_stack(limit=3,file=sys.stdout)
242       cs= CONTEXT.get_current_step()
243       if self != cs :
244          raise "L'étape courante %s devrait etre self : %s" % (cs,self)
245       else :
246          CONTEXT.unset_current_step()
247          CONTEXT.set_current_step(self.parent)
248
249    def issubstep(self,etape):
250       """ 
251           Cette methode retourne un entier indiquant si etape est une
252           sous etape de self ou non
253           1 = oui
254           0 = non
255           Une étape simple n'a pas de sous etape
256       """
257       return 0
258
259    def get_file(self,unite=None,fic_origine=''):
260       """ 
261          Retourne le nom du fichier associe a l unite logique unite (entier)
262          ainsi que le source contenu dans le fichier
263       """
264       if self.jdc : return self.jdc.get_file(unite=unite,fic_origine=fic_origine)
265       else :
266          file = None
267          if unite != None:
268             if os.path.exists("fort."+str(unite)):
269                file= "fort."+str(unite)
270          if file == None : 
271             raise AsException("Impossible de trouver le fichier correspondant a l unite %s" % unite)
272          if not os.path.exists(file): 
273             raise AsException("%s n'est pas un fichier existant" % unite)
274          fproc=open(file,'r')
275          text=string.replace(fproc.read(),'\r\n','\n')
276          fproc.close()
277          linecache.cache[file]=0,0,string.split(text,'\n'),file
278          return file,text
279
280    def accept(self,visitor):
281       """
282          Cette methode permet de parcourir l'arborescence des objets
283          en utilisant le pattern VISITEUR
284       """
285       visitor.visitETAPE(self)
286
287    def update_context(self,d):
288       """
289           Cette methode doit updater le contexte fournit par
290           l'appelant en argument (d) en fonction de sa definition
291       """
292       if type(self.definition.op_init) == types.FunctionType:
293         apply(self.definition.op_init,(self,d))
294       if self.sd:
295         d[self.sd.nom]=self.sd
296
297
298
299