2 Ce module contient la classe ETAPE qui sert à vérifier et à exécuter
7 import types,sys,string,os
13 from N_Exception import AsException
15 from N_utils import AsType
17 class ETAPE(N_MCCOMPO.MCCOMPO):
19 Cette classe hérite de MCCOMPO car ETAPE est un OBJECT composite
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é
28 def __init__(self,oper=None,reuse=None,args={}):
32 - definition : objet portant les attributs de définition d'une étape de type opérateur. Il
33 est initialisé par l'argument oper.
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
38 - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé avec l'argument args.
45 self.parent=CONTEXT.get_current_step()
48 self.idracine=oper.label
49 self.appel=N_utils.callee_where()
55 def make_register(self):
57 Initialise les attributs jdc, id, niveau et réalise les
58 enregistrements nécessaires
61 self.jdc = self.parent.get_jdc_root()
62 self.id=self.parent.register(self)
65 self.jdc = self.parent =None
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.
74 for k in self.valeur.keys():
75 if self.valeur[k] == None:del self.valeur[k]
79 Demande la construction des sous-objets et les stocke dans l'attribut
82 self.mc_liste=self.build_mc()
84 def Build_sd(self,nom):
86 Construit le concept produit de l'opérateur. Deux cas
87 peuvent se présenter :
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.
92 - le parent est défini. Dans ce cas, l'étape demande au parent la création et
93 le nommage du concept.
96 if not self.isactif():return
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))
103 sd=self.get_sd_prod()
104 # On n'utilise pas self.definition.op_init car self.parent
106 if sd != None and self.reuse == None:
107 # On ne nomme le concept que dans le cas de non reutilisation
110 if self.jdc and self.jdc.par_lot == "NON" :
113 except AsException,e:
114 raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
115 'fichier : ',self.appel[1],e)
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()
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',
129 Cette methode est prevue pour faire une execution dans le cas
131 Par defaut, elle ne fait rien
135 def get_sd_prod(self):
137 Retourne le concept résultat de l'étape
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
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
148 if type(self.definition.sd_prod) == types.FunctionType:
149 d=self.cree_dict_valeurs(self.mc_liste)
151 sd_prod= apply(self.definition.sd_prod,(),d)
155 if CONTEXT.debug: traceback.print_exc()
156 l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
158 raise AsException("impossible d affecter un type au resultat",
160 # sys.exc_info()[0],sys.exc_info()[1],)
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
165 if AsType(self.reuse) != sd_prod:
166 raise AsException("type de concept reutilise incompatible avec type produit")
169 self.sd= sd_prod(etape=self)
170 if self.definition.reentrant == 'o':
174 def get_type_produit(self):
176 Retourne le type du concept résultat de l'étape
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
185 if type(self.definition.sd_prod) == types.FunctionType:
186 d=self.cree_dict_valeurs(self.mc_liste)
188 sd_prod= apply(self.definition.sd_prod,(),d)
190 #traceback.print_exc()
193 sd_prod=self.definition.sd_prod
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 ????
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
210 N_MCCOMPO.MCCOMPO.supprime(self)
213 if self.sd : self.sd.supprime()
217 Indique si l'étape est active (1) ou inactive (0)
221 def set_current_step(self):
223 Methode utilisee pour que l etape self se declare etape
224 courante. Utilise par les macros
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)
232 CONTEXT.unset_current_step()
233 CONTEXT.set_current_step(self)
235 def reset_current_step(self):
237 Methode utilisee par l'etape self qui remet son etape parent comme
240 #print "reset_current_step ",self.nom
241 #traceback.print_stack(limit=3,file=sys.stdout)
242 cs= CONTEXT.get_current_step()
244 raise "L'étape courante %s devrait etre self : %s" % (cs,self)
246 CONTEXT.unset_current_step()
247 CONTEXT.set_current_step(self.parent)
249 def issubstep(self,etape):
251 Cette methode retourne un entier indiquant si etape est une
252 sous etape de self ou non
255 Une étape simple n'a pas de sous etape
259 def get_file(self,unite=None,fic_origine=''):
261 Retourne le nom du fichier associe a l unite logique unite (entier)
262 ainsi que le source contenu dans le fichier
264 if self.jdc : return self.jdc.get_file(unite=unite,fic_origine=fic_origine)
268 if os.path.exists("fort."+str(unite)):
269 file= "fort."+str(unite)
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)
275 text=string.replace(fproc.read(),'\r\n','\n')
277 linecache.cache[file]=0,0,string.split(text,'\n'),file
280 def accept(self,visitor):
282 Cette methode permet de parcourir l'arborescence des objets
283 en utilisant le pattern VISITEUR
285 visitor.visitETAPE(self)
287 def update_context(self,d):
289 Cette methode doit updater le contexte fournit par
290 l'appelant en argument (d) en fonction de sa definition
292 if type(self.definition.op_init) == types.FunctionType:
293 apply(self.definition.op_init,(self,d))
295 d[self.sd.nom]=self.sd