+#@ MODIF N_MACRO_ETAPE Noyau DATE 14/09/2004 AUTEUR MCOURTOI M.COURTOIS
+# -*- coding: iso-8859-1 -*-
+# CONFIGURATION MANAGEMENT OF EDF VERSION
+# ======================================================================
+# COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
+# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
+# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
+# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
+# (AT YOUR OPTION) ANY LATER VERSION.
+#
+# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
+# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
+# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
+# GENERAL PUBLIC LICENSE FOR MORE DETAILS.
+#
+# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
+# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
+# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
+#
+#
+# ======================================================================
+
+
"""
Ce module contient la classe MACRO_ETAPE qui sert à vérifier et à exécuter
une commande
"""
if not self.isactif():return
+ self.sdnom=nom
try:
# On positionne la macro self en tant que current_step pour que les
# étapes créées lors de l'appel à sd_prod et à op_init aient la macro
# d un concept
sd.nom=nom
self.reset_current_step()
- if self.jdc and self.jdc.par_lot == "NON" :
- self.Execute()
- return sd
except AsException,e:
self.reset_current_step()
raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
'fichier : ',self.appel[1],e)
- except EOFError:
- #self.reset_current_step()
+ except (EOFError,self.jdc.UserError):
+ # Le retablissement du step courant n'est pas strictement necessaire. On le fait pour des raisons de coherence
+ self.reset_current_step()
raise
except :
self.reset_current_step()
'fichier : ',self.appel[1]+'\n',
string.join(l))
+ self.Execute()
+ return sd
+
def get_sd_prod(self):
"""
Retourne le concept résultat d'une macro étape
# les concepts produits dans self.sdprods, il faut le mettre à zéro avant de l'appeler
self.sdprods=[]
sd_prod= apply(sd_prod,(self,),d)
- except EOFError:
+ except (EOFError,self.jdc.UserError):
raise
except:
if CONTEXT.debug: traceback.print_exc()
raise AsException("impossible d affecter un type au resultat\n",string.join(l[2:]))
# on teste maintenant si la SD est réutilisée ou s'il faut la créer
- if self.reuse:
- if AsType(self.reuse) != sd_prod:
- raise AsException("type de concept reutilise incompatible avec type produit")
+ if self.definition.reentrant != 'n' and self.reuse:
+ # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
+ # Elle sera traitee ulterieurement.
self.sd=self.reuse
else:
if sd_prod == None:
else:
self.sd= sd_prod(etape=self)
self.typret=sd_prod
- if self.definition.reentrant == 'o':
- self.reuse = self.sd
+ # Si la commande est obligatoirement reentrante et reuse n'a pas ete specifie, c'est une erreur.
+ # On ne fait rien ici. L'erreur sera traitee par la suite.
return self.sd
def get_type_produit(self,force=0):
# mémorisée dans self.index_etape_courante
# Si on insère des commandes (par ex, dans EFICAS), il faut
# préalablement remettre ce pointeur à 0
- index_etape=self.etapes.index(etape)
+ if etape:
+ index_etape=self.etapes.index(etape)
+ else:
+ index_etape=len(self.etapes)
+
if index_etape >= self.index_etape_courante:
# On calcule le contexte en partant du contexte existant
d=self.current_context
def supprime(self):
"""
Méthode qui supprime toutes les références arrières afin que
- l'objet puisse être correctement détruit par le garbage collector
+ l'objet puisse etre correctement détruit par le garbage collector
"""
N_MCCOMPO.MCCOMPO.supprime(self)
self.jdc=None
raise AsException("Le type du concept produit %s devrait etre une sur classe de %s" %(sd.__class__,sdprod))
# La propriete du concept est transferee a l'etape avec le type attendu par l'étape
etape.sd=sd
- #sd.__call__=sdprod
- #XXX Il semble plus logique que ce soit class et non pas call ???
- sd.__class__=sdprod
sd.etape=etape
+ # On donne au concept le type produit par la sous commande.
+ # Le principe est le suivant : apres avoir verifie que le type deduit par la sous commande
+ # est bien coherent avec celui initialement affecte par la macro (voir ci dessus)
+ # on affecte au concept ce type car il peut etre plus precis (derive, en general)
+ sd.__class__=sdprod
+ # On force également le nom stocké dans l'attribut sdnom : on lui donne le nom
+ # du concept associé à nomsd
+ etape.sdnom=sd.nom
+ elif etape.definition.reentrant != 'n' and etape.reuse != None:
+ # On est dans le cas d'une commande avec reutilisation d'un concept existant
+ # get_sd_prod fait le necessaire : verifications, associations, etc. mais ne cree
+ # pas un nouveau concept. Il retourne le concept reutilise
+ sd= etape.get_sd_prod()
+ # Dans le cas d'un concept nomme automatiquement : _xxx, __xxx,
+ # On force le nom stocke dans l'attribut sdnom de l'objet etape : on lui donne le nom
+ # du concept reutilise (sd ou etape.reuse c'est pareil)
+ # Ceci est indispensable pour eviter des erreurs lors des verifications des macros
+ # En effet une commande avec reutilisation d'un concept verifie que le nom de
+ # la variable a gauche du signe = est le meme que celui du concept reutilise.
+ # Lorsqu'une telle commande apparait dans une macro, on supprime cette verification.
+ if (etape.sdnom == '' or etape.sdnom[0] == '_'):
+ etape.sdnom=sd.nom
else:
+ # On est dans le cas de la creation d'un nouveau concept
sd= etape.get_sd_prod()
- if sd != None and etape.reuse == None:
- # ATTENTION : On ne nomme la SD que dans le cas de non reutilisation d un concept
+ if sd != None :
self.NommerSdprod(sd,nomsd)
return sd
- def NommerSdprod(self,sd,sdnom):
+ def NommerSdprod(self,sd,sdnom,restrict='non'):
"""
Cette methode est appelee par les etapes internes de la macro
La macro appelle le JDC pour valider le nommage
On considere que l espace de nom est unique et géré par le JDC
Si le nom est deja utilise, l appel leve une exception
+ Si restrict=='non', on insere le concept dans le contexte de la macro
+ Si restrict=='oui', on n'insere pas le concept dans le contexte de la macro
"""
+ # Normalement, lorsqu'on appelle cette methode, on ne veut nommer que des concepts nouvellement crees.
+ # Le filtrage sur les concepts a creer ou a ne pas creer est fait dans la methode
+ # create_sdprod. La seule chose a verifier apres conversion eventuelle du nom
+ # est de verifier que le nom n'est pas deja attribue. Ceci est fait en delegant
+ # au JDC par l'intermediaire du parent.
+
#XXX attention inconsistence : prefix et gcncon ne sont pas
# définis dans le package Noyau. La methode NommerSdprod pour
# les macros devrait peut etre etre déplacée dans Build ???
+
if CONTEXT.debug : print "MACRO.NommerSdprod: ",sd,sdnom
+
if hasattr(self,'prefix'):
# Dans le cas de l'include_materiau on ajoute un prefixe au nom du concept
if sdnom != self.prefix:sdnom=self.prefix+sdnom
+
if self.Outputs.has_key(sdnom):
# Il s'agit d'un concept de sortie de la macro produit par une sous commande
sdnom=self.Outputs[sdnom].nom
- elif sdnom[0] == '_':
+ elif sdnom != '' and sdnom[0] == '_':
# Si le nom du concept commence par le caractere _ on lui attribue
# un identificateur JEVEUX construit par gcncon et respectant
# la regle gcncon legerement adaptee ici
sdnom=self.gcncon('.')
else:
sdnom=self.gcncon('_')
- if self.sd != None and self.sd.nom == sdnom :
- # Il s'agit du concept produit par la macro, il a deja ete nomme.
- # On se contente de donner le meme nom au concept produit par la sous commande
- # sans passer par la routine de nommage
- sd.nom=sdnom
else:
- # On propage le nommage au contexte superieur
- self.parent.NommerSdprod(sd,sdnom)
+ # On est dans le cas d'un nom de concept global.
+ pass
+
+ if restrict == 'non':
+ # On demande le nommage au parent mais sans ajout du concept dans le contexte du parent
+ # car on va l'ajouter dans le contexte de la macro
+ self.parent.NommerSdprod(sd,sdnom,restrict='oui')
+ # On ajoute dans le contexte de la macro les concepts nommes
+ # Ceci est indispensable pour les CO (macro) dans un INCLUDE
+ self.g_context[sdnom]=sd
+ else:
+ # La demande de nommage vient probablement d'une macro qui a mis
+ # le concept dans son contexte. On ne traite plus que le nommage (restrict="oui")
+ self.parent.NommerSdprod(sd,sdnom,restrict='oui')
def delete_concept_after_etape(self,etape,sd):
"""
"""
Inclut un fichier poursuite
"""
- f,text=self.get_file(fic_origine=self.parent.nom)
+ try:
+ f,text=self.get_file(fic_origine=self.parent.nom)
+ except:
+ raise AsException("Impossible d'ouvrir la base pour une poursuite")
self.fichier_init=f
if f == None:return
self.make_contexte(f,text)
d={}
self.g_context = d
self.contexte_fichier_init = d
- exec code in self.parent.g_context,d
+ globs=self.parent.get_global_contexte()
+ exec code in globs,d
+
+ def get_global_contexte(self):
+ """
+ Cette methode retourne le contexte global fourni
+ par le parent(self) a une etape fille (l'appelant) pour
+ realiser des evaluations de texte Python (INCLUDE,...)
+ """
+ # Le contexte global est forme par concatenation du contexte
+ # du parent de self et de celui de l'etape elle meme (self)
+ d=self.parent.get_global_contexte()
+ d.update(self.g_context)
+ return d
+
+ def copy(self):
+ """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
+ et sans sd
+ On surcharge la methode de ETAPE pour exprimer que les concepts crees
+ par la MACRO d'origine ne sont pas crees par la copie mais eventuellement
+ seulement utilises
+ """
+ etape=N_ETAPE.ETAPE.copy(self)
+ etape.sdprods=[]
+ return etape
+
+ def copy_intern(self,etape):
+ """ Cette méthode effectue la recopie des etapes internes d'une macro
+ passée en argument (etape)
+ """
+ self.etapes=[]
+ for etp in etape.etapes:
+ new_etp=etp.copy()
+ new_etp.copy_reuse(etp)
+ new_etp.copy_sdnom(etp)
+ new_etp.reparent(self)
+ if etp.sd:
+ new_sd = etp.sd.__class__(etape=new_etp)
+ new_etp.sd = new_sd
+ if etp.reuse:
+ new_sd.nom = etp.sd.nom
+ else:
+ self.NommerSdprod(new_sd,etp.sd.nom)
+ new_etp.copy_intern(etp)
+ self.etapes.append(new_etp)