2 # Copyright (C) 2007-2017 EDF R&D
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 Ce module contient la classe MACRO_ETAPE qui sert a verifier et a executer
27 from __future__ import absolute_import
28 from __future__ import print_function
30 from builtins import str
35 from warnings import warn
38 from . import N_MCCOMPO
40 from .N_Exception import AsException
42 from .N_utils import AsType
44 from .N_ASSD import ASSD
47 class MACRO_ETAPE(N_ETAPE.ETAPE):
55 def __init__(self, oper=None, reuse=None, args={}):
58 - definition : objet portant les attributs de definition d'une etape
59 de type macro-commande. Il est initialise par
61 - reuse : indique le concept d'entree reutilise. Il se trouvera donc
62 en sortie si les conditions d'execution de l'operateur
64 - valeur : arguments d'entree de type mot-cle=valeur. Initialise
67 N_ETAPE.ETAPE.__init__(self, oper, reuse, args, niveau=5)
70 self.currentContext = {}
71 self.macro_const_context = {}
72 self.index_etape_courante = 0
74 self.index_etapes = {}
75 # Dans le cas d'une macro ecrite en Python, l'attribut Outputs est un
76 # dictionnaire qui contient les concepts produits de sortie
77 # (nom : ASSD) declares dans la fonction sd_prod
80 self.UserError = "UserError"
81 # permet de stocker le nom du dernier concept nomme dans la macro
84 def makeRegister(self):
86 Initialise les attributs jdc, id, niveau et realise les enregistrements
89 N_ETAPE.ETAPE.makeRegister(self)
91 self.UserError = self.jdc.UserError
93 self.UserError = "UserError"
95 def buildSd(self, nom):
97 Construit le concept produit de l'operateur. Deux cas
98 peuvent se presenter :
100 - le parent n'est pas defini. Dans ce cas, l'etape prend en charge
101 la creation et le nommage du concept.
103 - le parent est defini. Dans ce cas, l'etape demande au parent la
104 creation et le nommage du concept.
109 # On positionne la macro self en tant que current_step pour que les
110 # etapes creees lors de l'appel a sd_prod et a op_init aient la macro
112 self.setCurrentStep()
114 sd = self.parent.createSdprod(self, nom)
115 if type(self.definition.op_init) == types.FunctionType:
116 self.definition.op_init(*(
117 self, self.parent.g_context))
119 sd = self.getSdProd()
120 if sd != None and self.reuse == None:
121 # On ne nomme le concept que dans le cas de non reutilisation
124 self.resetCurrentStep()
125 except AsException as e:
126 self.resetCurrentStep()
127 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
128 'fichier : ', self.appel[1], e)
129 #except (EOFError, self.UserError):
131 # Le retablissement du step courant n'est pas strictement
132 # necessaire. On le fait pour des raisons de coherence
133 self.resetCurrentStep()
136 self.resetCurrentStep()
137 l = traceback.format_exception(
138 sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])
139 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
140 'fichier : ', self.appel[1] + '\n',
148 Retourne le concept resultat d'une macro etape
149 La difference avec une etape ou une proc-etape tient a ce que
150 le concept produit peut exister ou pas
152 Si sd_prod == None le concept produit n existe pas on retourne None
155 - cas 1 : sd_prod n'est pas une fonction
156 il s'agit d'une sous classe de ASSD
157 on construit le sd a partir de cette classe
159 - cas 2 : sd_prod est une fonction
160 on l'evalue avec les mots-cles de l'etape (mcListe)
161 on construit le sd a partir de la classe obtenue
164 sd_prod = self.definition.sd_prod
167 if type(self.definition.sd_prod) == types.FunctionType:
168 d = self.creeDictValeurs(self.mcListe)
170 # la sd_prod d'une macro a l'objet macro_etape lui meme en premier argument
171 # Comme sd_prod peut invoquer la methode typeSDProd qui ajoute
172 # les concepts produits dans self.sdprods, il faut le mettre a
173 # zero avant de l'appeler
175 sd_prod = sd_prod(*(self,), **d)
176 #except (EOFError, self.UserError):
179 except Exception as exc:
181 traceback.print_exc()
182 raise AsException("impossible d affecter un type au resultat:",
185 # on teste maintenant si la SD est reutilisee ou s'il faut la creer
186 if self.definition.reentrant != 'n' and self.reuse:
187 # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
188 # Elle sera traitee ulterieurement.
194 self.sd = sd_prod(etape=self)
195 self.typret = sd_prod
196 # Si la commande est obligatoirement reentrante et reuse n'a pas ete specifie, c'est une erreur.
197 # On ne fait rien ici. L'erreur sera traitee par la suite.
199 if self.sd is not None and not isinstance(self.sd, ASSD):
200 raise AsException("""
201 Impossible de typer le resultat !
203 Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte,
204 soit il y a une "," a la fin d'une commande precedente.
205 Developpeur : La fonction "sd_prod" retourne un type invalide.""")
208 def getType_produit(self, force=0):
210 return self.getType_produit_brut(force)
212 # traceback.print_exc()
215 def getType_produit_brut(self, force=0):
217 Retourne le type du concept resultat de l'etape et eventuellement type
218 les concepts produits "a droite" du signe egal (en entree)
221 - cas 1 : sd_prod de oper n'est pas une fonction
222 il s'agit d'une sous classe de ASSD
223 on retourne le nom de la classe
224 - cas 2 : il s'agit d'une fonction
225 on l'evalue avec les mots-cles de l'etape (mcListe)
226 et on retourne son resultat
228 if not force and hasattr(self, 'typret'):
231 if type(self.definition.sd_prod) == types.FunctionType:
232 d = self.creeDictValeurs(self.mcListe)
233 # Comme sd_prod peut invoquer la methode typeSDProd qui ajoute
234 # les concepts produits dans self.sdprods, il faut le mettre a zero
236 sd_prod = self.definition.sd_prod(*(self,), **d)
238 sd_prod = self.definition.sd_prod
241 def getContexteAvant(self, etape):
243 Retourne le dictionnaire des concepts connus avant etape
244 pour les commandes internes a la macro
245 On tient compte des commandes qui modifient le contexte
246 comme DETRUIRE ou les macros
248 # L'etape courante pour laquelle le contexte a ete calcule est
249 # memorisee dans self.index_etape_courante
250 # self.currentContext.items() if isinstance(v, ASSD)])
251 d = self.currentContext = self.g_context.copy()
254 # retirer les sd produites par 'etape'
255 sd_names = [sd.nom for sd in etape.getCreated_sd()]
261 # Exemple avec INCLUDE_MATERIAU appele dans une macro.
262 # Les fonctions restent uniquement dans le contexte de INCLUDE_MATERIAU,
263 # elles ne sont donc pas dans le contexte de la macro appelante.
264 # from warnings import warn
265 # warn("concept '%s' absent du contexte de %s" % (nom, self.nom),
266 # RuntimeWarning, stacklevel=2)
271 Methode qui supprime toutes les references arrières afin que
272 l'objet puisse etre correctement detruit par le garbage collector
274 N_MCCOMPO.MCCOMPO.supprime(self)
279 for concept in self.sdprods:
281 for etape in self.etapes:
284 def clean(self, netapes):
285 """Nettoie les `netapes` dernières etapes de la liste des etapes."""
286 if self.jdc.hist_etape:
288 for i in range(netapes):
289 e = self.etapes.pop()
295 del self.index_etapes[e]
297 def typeSDProd(self, co, t):
299 Cette methode a pour fonction de typer le concept co avec le type t
300 dans les conditions suivantes :
301 1. co est un concept produit de self
302 2. co est un concept libre : on le type et on l attribue a self
304 Elle enregistre egalement les concepts produits (on fait l hypothese
305 que la liste sdprods a ete correctement initialisee, vide probablement)
307 if not hasattr(co, 'etape'):
308 # Le concept vaut None probablement. On ignore l'appel
311 # On cherche a discriminer les differents cas de typage d'un concept
312 # produit par une macro qui est specifie dans un mot cle simple.
313 # On peut passer plusieurs fois par typeSDProd ce qui explique
314 # le nombre important de cas.
316 # Cas 1 : Le concept est libre. Il vient d'etre cree par CO(nom)
317 # Cas 2 : Le concept est produit par la macro. On est deja passe par typeSDProd.
318 # Cas semblable a Cas 1.
319 # Cas 3 : Le concept est produit par la macro englobante (parent). On transfere
320 # la propriete du concept de la macro parent a la macro courante (self)
321 # en verifiant que le type est valide
322 # Cas 4 : La concept est la propriete d'une etape fille. Ceci veut dire qu'on est
323 # deja passe par typeSDProd et que la propriete a ete transfere a une
324 # etape fille. Cas semblable a Cas 3.
325 # Cas 5 : Le concept est produit par une etape externe a la macro.
328 # Cas 1 : le concept est libre
329 # On l'attache a la macro et on change son type dans le type demande
330 # Recherche du mot cle simple associe au concept
331 mcs = self.getMcsWithCo(co)
333 raise AsException("""Erreur interne.
334 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
336 if not self.typeCO in mcs.definition.type:
337 raise AsException("""Erreur interne.
338 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" % (co, mcs.definition.type))
340 # affectation du bon type du concept
342 self.sdprods.append(co)
344 elif co.etape == self:
345 # Cas 2 : le concept est produit par la macro (self)
346 # On est deja passe par typeSDProd (Cas 1 ou 3).
347 # XXX Peut-il etre creer par une autre macro ?
348 # On verifie juste que c'est un vrai CO non deja type
349 # if co.etape == co._etape:
350 if co.isTypCO() == 1:
351 # Le concept a ete cree par la macro (self)
352 # On peut changer son type
355 # Le concept a ete cree par une macro parente
356 # Le type du concept doit etre coherent avec le type demande
358 if not isinstance(co, t):
359 raise AsException("""Erreur interne.
360 Le type demande (%s) et le type du concept (%s) devraient etre derives""" % (t, co.__class__))
362 self.sdprods.append(co)
364 elif co.etape == self.parent:
365 # Cas 3 : le concept est produit par la macro parente (self.parent)
366 # on transfere la propriete du concept a la macro fille
367 # et on change le type du concept comme demande
368 # Au prealable, on verifie que le concept existant (co) est une instance
369 # possible du type demande (t)
370 # Cette règle est normalement coherente avec les règles de
371 # verification des mots-cles
372 if not isinstance(co, t):
373 raise AsException("""
374 Impossible de changer le type du concept produit (%s) en (%s).
375 Le type actuel (%s) devrait etre une classe derivee du nouveau type (%s)""" % (co, t, co.__class__, t))
376 mcs = self.getMcsWithCo(co)
378 raise AsException("""Erreur interne.
379 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
381 if not self.typeCO in mcs.definition.type:
382 raise AsException("""Erreur interne.
383 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" % (co, mcs.definition.type))
385 # On ne change pas le type car il respecte la condition isinstance(co,t)
387 self.sdprods.append(co)
389 elif self.issubstep(co.etape):
390 # Cas 4 : Le concept est propriete d'une sous etape de la macro (self).
391 # On est deja passe par typeSDProd (Cas 3 ou 1).
392 # Il suffit de le mettre dans la liste des concepts produits (self.sdprods)
393 # Le type du concept et t doivent etre derives.
394 # Il n'y a aucune raison pour que la condition ne soit pas
396 if not isinstance(co, t):
397 raise AsException("""Erreur interne.
398 Le type demande (%s) et le type du concept (%s) devraient etre derives""" % (t, co.__class__))
399 self.sdprods.append(co)
402 # Cas 5 : le concept est produit par une autre etape
406 def issubstep(self, etape):
408 Cette methode retourne un entier indiquant si etape est une
409 sous etape de la macro self ou non
413 if etape in self.etapes:
415 for etap in self.etapes:
416 if etap.issubstep(etape):
420 def register(self, etape):
422 Enregistrement de etape dans le contexte de la macro : liste etapes
423 et demande d enregistrement global aupres du JDC
425 self.etapes.append(etape)
426 self.index_etapes[etape] = len(self.etapes) - 1
427 idetape = self.jdc.gRegister(etape)
432 Methode appelee dans l __init__ d un ASSD a sa creation pour
433 s enregistrer (reserve aux ASSD crees au sein d'une MACRO)
435 return self.jdc.o_register(sd)
437 def createSdprod(self, etape, nomsd):
439 Cette methode doit fabriquer le concept produit retourne
440 par l'etape etape et le nommer.
442 Elle est appelee a l'initiative de l'etape
443 pendant le processus de construction de cette etape : methode __call__
444 de la classe CMD (OPER ou MACRO)
445 Ce travail est realise par le contexte superieur (etape.parent)
446 car dans certains cas, le concept ne doit pas etre fabrique mais
447 l'etape doit simplement utiliser un concept preexistant.
448 - Cas 1 : etape.reuse != None : le concept est reutilise
449 - Cas 2 : l'etape appartient a une macro qui a declare un concept
450 de sortie qui doit etre produit par cette etape.
452 if nomsd in self.Outputs:
453 # Il s'agit d'un concept de sortie de la macro. Il ne faut pas le creer
454 # Il faut quand meme appeler la fonction sd_prod si elle existe.
455 # getType_produit le fait et donne le type attendu par la commande
456 # pour verification ulterieure.
457 sdprod = etape.getType_produit_brut()
458 sd = self.Outputs[nomsd]
459 # On verifie que le type du concept existant sd.__class__ est un sur type de celui attendu
460 # Cette règle est normalement coherente avec les règles de
461 # verification des mots-cles
462 if not issubclass(sdprod, sd.__class__):
464 "Le type du concept produit %s devrait etre une sur classe de %s" % (sd.__class__, sdprod))
465 # La propriete du concept est transferee a l'etape avec le type
466 # attendu par l'etape
469 if self.reuse == sd and etape.reuse != sd \
470 and getattr(sd, "executed", 0) == 1: # n'a pas ete pas detruit
471 raise AsException("Le concept '%s' est reentrant dans la macro-commande %s. "
472 "Il devrait donc l'etre dans %s (produit sous le nom '%s')."
473 % (sd.nom, self.nom, etape.nom, nomsd))
474 # On donne au concept le type produit par la sous commande.
475 # Le principe est le suivant : apres avoir verifie que le type deduit par la sous commande
476 # est bien coherent avec celui initialement affecte par la macro (voir ci dessus)
477 # on affecte au concept ce type car il peut etre plus precis
478 # (derive, en general)
479 sd.__class__ = sdprod
480 # On force egalement le nom stocke dans l'attribut sdnom : on lui donne le nom
481 # du concept associe a nomsd
483 # pour l'ajouter au contexte de la macro
484 self.g_context[sd.nom] = sd
485 elif etape.definition.reentrant != 'n' and etape.reuse != None:
486 # On est dans le cas d'une commande avec reutilisation d'un concept existant
487 # getSdProd fait le necessaire : verifications, associations, etc. mais ne cree
488 # pas un nouveau concept. Il retourne le concept reutilise
489 sd = etape.getSdProd()
490 # Dans le cas d'un concept nomme automatiquement : _xxx, __xxx,
491 # On force le nom stocke dans l'attribut sdnom de l'objet etape : on lui donne le nom
492 # du concept reutilise (sd ou etape.reuse c'est pareil)
493 # Ceci est indispensable pour eviter des erreurs lors des verifications des macros
494 # En effet une commande avec reutilisation d'un concept verifie que le nom de
495 # la variable a gauche du signe = est le meme que celui du concept reutilise.
496 # Lorsqu'une telle commande apparait dans une macro, on supprime
497 # cette verification.
498 if (etape.sdnom == '' or etape.sdnom[0] == '_'):
501 # On est dans le cas de la creation d'un nouveau concept
502 sd = etape.getSdProd()
504 self.nommerSDProd(sd, nomsd)
507 def nommerSDProd(self, sd, sdnom, restrict='non'):
509 Cette methode est appelee par les etapes internes de la macro.
510 La macro appelle le JDC pour valider le nommage.
511 On considère que l'espace de nom est unique et gere par le JDC.
512 Si le nom est deja utilise, l'appel lève une exception.
513 Si restrict=='non', on insère le concept dans le contexte du parent de la macro.
514 Si restrict=='oui', on insère le concept uniquement dans le contexte de la macro.
516 # Normalement, lorsqu'on appelle cette methode, on ne veut nommer que des concepts nouvellement crees.
517 # Le filtrage sur les concepts a creer ou a ne pas creer est fait dans la methode
518 # createSdprod. La seule chose a verifier apres conversion eventuelle du nom
519 # est de verifier que le nom n'est pas deja attribue. Ceci est fait en delegant
520 # au JDC par l'intermediaire du parent.
521 if sdnom in self.Outputs :
522 # Il s'agit d'un concept de sortie de la macro produit par une
524 sdnom = self.Outputs[sdnom].nom
526 if sdnom[0] in ('_', '.') and sdnom[1:].isdigit():
527 # il est deja de la forme _9000012 ou .9000017
529 elif sdnom[0] == '_':
530 # Si le nom du concept commence par le caractère '_', on lui attribue
531 # un identificateur JEVEUX construit par gcncon.
532 # nom commençant par __ : il s'agit de concepts qui seront detruits
533 # nom commençant par _ : il s'agit de concepts intermediaires
535 if len(sdnom) > 1 and sdnom[1] == '_':
536 sdnom = self.gcncon('.')
538 sdnom = self.gcncon('_')
539 elif self.nom in ('INCLUDE', 'MACR_RECAL'):
540 # dans le cas d'INCLUDE, on passe
541 # MACR_RECAL fonctionne comme INCLUDE
544 # On est dans le cas d'un nom de concept global
545 # XXX a voir, creation de CO() dans CALC_ESSAI (sdls139a)
548 "Resultat non declare par la macro %s : %s" % (self.nom, sdnom))
550 if restrict == 'non':
551 # On demande le nommage au parent mais sans ajout du concept dans le contexte du parent
552 # car on va l'ajouter dans le contexte de la macro
553 self.parent.nommerSDProd(sd, sdnom, restrict='oui')
554 # On ajoute dans le contexte de la macro les concepts nommes
555 # Ceci est indispensable pour les CO (macro) dans un INCLUDE
556 self.g_context[sdnom] = sd
558 # La demande de nommage vient probablement d'une macro qui a mis
559 # le concept dans son contexte. On ne traite plus que le nommage (restrict="oui")
560 self.parent.nommerSDProd(sd, sdnom, restrict='oui')
562 def deleteConceptAfterEtape(self, etape, sd):
564 Met a jour les etapes de la MACRO qui sont après etape suite a
565 la disparition du concept sd
567 # Cette methode est definie dans le noyau mais ne sert que pendant la phase de creation
568 # des etapes et des concepts. Il n'y a aucun traitement particulier a realiser
569 # Dans d'autres conditions, il faudrait surcharger cette methode.
572 def getCreated_sd(self):
573 """Retourne la liste des sd reellement produites par l'etape.
574 Si reuse est present, `self.sd` a ete creee avant, donc n'est pas dans
576 sdprods = self.sdprods[:]
577 if not self.reuse and self.sd:
578 sdprods.append(self.sd)
581 def getLastConcept(self):
582 """Retourne le dernier concept produit dans la macro.
583 Peut-etre utile pour acceder au contenu 'fortran' dans une
585 return self.g_context.get(self.last, None)
587 def accept(self, visitor):
589 Cette methode permet de parcourir l'arborescence des objets
590 en utilisant le pattern VISITEUR
592 visitor.visitMACRO_ETAPE(self)
594 def updateContext(self, d):
596 Met a jour le contexte contenu dans le dictionnaire d
597 Une MACRO_ETAPE peut ajouter plusieurs concepts dans le contexte
598 Une fonction enregistree dans op_init peut egalement modifier le contexte
600 if type(self.definition.op_init) == types.FunctionType:
601 self.definition.op_init(*(self, d))
603 d[self.sd.nom] = self.sd
604 for co in self.sdprods:
607 def makeInclude(self, unite=None, fname=None):
608 """Inclut un fichier dont l'unite logique est `unite` ou de nom `fname`"""
609 if unite is not None:
610 warn("'unite' is deprecated, please use 'fname' instead",
611 DeprecationWarning, stacklevel=2)
612 fname = 'fort.%s' % unite
615 f, text = self.getFile(fic_origine=self.parent.nom, fname=fname)
616 self.fichier_init = f
619 self.makeContexte(f, text)
621 def makePoursuite(self):
622 """Inclut un fichier poursuite"""
623 raise NotImplementedError('this method must be derivated (in Eficas)')
625 def makeContexte(self, f, text):
627 Interprete le texte fourni (text) issu du fichier f
628 dans le contexte du parent.
629 Cette methode est utile pour le fonctionnement des
632 # on execute le texte fourni dans le contexte forme par
633 # le contexte de l etape pere (global au sens Python)
634 # et le contexte de l etape (local au sens Python)
635 code = compile(text, f, 'exec')
636 d = self.g_context = self.macro_const_context
637 globs = self.getGlobalContexte()
640 # pour ne pas conserver des references sur tout
641 self.macro_const_context = {}
643 def getGlobalContexte(self):
645 Cette methode retourne le contexte global fourni
646 par le parent(self) a une etape fille (l'appelant) pour
647 realiser des evaluations de texte Python (INCLUDE,...)
649 # Le contexte global est forme par concatenation du contexte
650 # du parent de self et de celui de l'etape elle meme (self)
651 # Pour les concepts, cela ne doit rien changer. Mais pour les constantes,
652 # les valeurs de getContexteAvant sont moins recentes que dans
653 # getGlobalContexte. On prend donc la precaution de ne pas ecraser
655 d = self.parent.getGlobalContexte()
656 d.update(self.g_context)
657 d.update([(k, v) for k, v in list(self.parent.getContexteAvant(self).items())
658 if d.get(k) is None])
661 def getContexteCourant(self, etape_fille_du_jdc=None):
663 Retourne le contexte tel qu'il est au moment de l'execution de
667 # update car par ricochet on modifierait jdc.currentContext
668 ctx.update(self.parent.getContexteCourant(self))
669 # on peut mettre None car toujours en PAR_LOT='NON', donc la dernière
670 ctx.update(self.getContexteAvant(None))
673 def getConcept(self, nomsd):
675 Methode pour recuperer un concept a partir de son nom
676 dans le contexte du jdc connu avant l'execution de la macro courante.
678 # chercher dans self.getContexteAvant, puis si non trouve
679 # self.parent.getConcept est peut-etre plus performant
680 co = self.getContexteCourant().get(nomsd.strip(), None)
681 if not isinstance(co, ASSD):
685 def getConceptByType(self, nomsd, typesd, etape=None):
687 Methode pour recuperer un concept a partir de son nom et de son type.
688 Il aura comme père 'etape' (ou la macro courante si etape est absente).
690 return self.parent.getConceptByType(nomsd, typesd, etape=etape or self)
693 """ Methode qui retourne une copie de self non enregistree auprès du JDC
695 On surcharge la methode de ETAPE pour exprimer que les concepts crees
696 par la MACRO d'origine ne sont pas crees par la copie mais eventuellement
699 etape = N_ETAPE.ETAPE.copy(self)
703 def copyIntern(self, etape):
704 """ Cette methode effectue la recopie des etapes internes d'une macro
705 passee en argument (etape)
708 self.index_etapes = {}
709 for etp in etape.etapes:
711 new_etp.copyReuse(etp)
712 new_etp.copySdnom(etp)
713 new_etp.reparent(self)
715 new_sd = etp.sd.__class__(etape=new_etp)
718 new_sd.setName(etp.sd.nom)
720 self.nommerSDProd(new_sd, etp.sd.nom)
721 new_etp.copyIntern(etp)
722 self.etapes.append(new_etp)
723 self.index_etapes[new_etp] = len(self.etapes) - 1
725 def resetJdc(self, new_jdc):
727 Reinitialise l'etape avec un nouveau jdc parent new_jdc
729 if self.sd and self.reuse == None:
730 self.parent.nommerSDProd(self.sd, self.sd.nom)
731 for concept in self.sdprods:
732 self.parent.nommerSDProd(concept, concept.nom)
734 def reparent(self, parent):
736 Cette methode sert a reinitialiser la parente de l'objet
738 N_ETAPE.ETAPE.reparent(self, parent)
739 # on ne change pas la parente des concepts. On s'assure uniquement que
740 # le jdc en reference est le bon
741 for concept in self.sdprods:
742 concept.jdc = self.jdc
743 for e in self.etapes:
746 def updateConstContext(self, d):
748 Met a jour le contexte des constantes pour l'evaluation de
749 formules dans la macro.
751 # Dans le jdc, const_context est mis a jour par execCompile
752 # Dans la macro, on n'a pas le code a compiler pour recupèrer les
753 # constantes locales a la macro. On demande donc explicitement de
754 # definir les constantes "locales".
755 self.macro_const_context.update(d)
757 def sdAccessible(self):
758 """On peut acceder aux "valeurs" (jeveux) des ASSD dans
759 les macro-commandes qui sont localement en PAR_LOT="NON"
763 print((' `- MACRO sdAccessible :', self.nom))
764 return self.parent.sdAccessible() or not self.isInclude()