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
31 from builtins import range
36 from warnings import warn
39 from . import N_MCCOMPO
41 from .N_Exception import AsException
43 from .N_utils import AsType
45 from .N_ASSD import ASSD
46 from six.moves import range
49 class MACRO_ETAPE(N_ETAPE.ETAPE):
57 def __init__(self, oper=None, reuse=None, args={}):
60 - definition : objet portant les attributs de definition d'une etape
61 de type macro-commande. Il est initialise par
63 - reuse : indique le concept d'entree reutilise. Il se trouvera donc
64 en sortie si les conditions d'execution de l'operateur
66 - valeur : arguments d'entree de type mot-cle=valeur. Initialise
69 N_ETAPE.ETAPE.__init__(self, oper, reuse, args, niveau=5)
72 self.current_context = {}
73 self.macro_const_context = {}
74 self.index_etape_courante = 0
76 self.index_etapes = {}
77 # Dans le cas d'une macro ecrite en Python, l'attribut Outputs est un
78 # dictionnaire qui contient les concepts produits de sortie
79 # (nom : ASSD) declares dans la fonction sd_prod
82 self.UserError = "UserError"
83 # permet de stocker le nom du dernier concept nomme dans la macro
86 def makeRegister(self):
88 Initialise les attributs jdc, id, niveau et realise les enregistrements
91 N_ETAPE.ETAPE.makeRegister(self)
93 self.UserError = self.jdc.UserError
95 self.UserError = "UserError"
97 def buildSd(self, nom):
99 Construit le concept produit de l'operateur. Deux cas
100 peuvent se presenter :
102 - le parent n'est pas defini. Dans ce cas, l'etape prend en charge
103 la creation et le nommage du concept.
105 - le parent est defini. Dans ce cas, l'etape demande au parent la
106 creation et le nommage du concept.
111 # On positionne la macro self en tant que current_step pour que les
112 # etapes creees lors de l'appel a sd_prod et a op_init aient la macro
114 self.setCurrentStep()
116 sd = self.parent.createSdprod(self, nom)
117 if type(self.definition.op_init) == types.FunctionType:
118 self.definition.op_init(*(
119 self, self.parent.g_context))
121 sd = self.getSdProd()
122 if sd != None and self.reuse == None:
123 # On ne nomme le concept que dans le cas de non reutilisation
126 self.resetCurrentStep()
127 except AsException as e:
128 self.resetCurrentStep()
129 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
130 'fichier : ', self.appel[1], e)
131 #except (EOFError, self.UserError):
133 # Le retablissement du step courant n'est pas strictement
134 # necessaire. On le fait pour des raisons de coherence
135 self.resetCurrentStep()
138 self.resetCurrentStep()
139 l = traceback.format_exception(
140 sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])
141 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
142 'fichier : ', self.appel[1] + '\n',
150 Retourne le concept resultat d'une macro etape
151 La difference avec une etape ou une proc-etape tient a ce que
152 le concept produit peut exister ou pas
154 Si sd_prod == None le concept produit n existe pas on retourne None
157 - cas 1 : sd_prod n'est pas une fonction
158 il s'agit d'une sous classe de ASSD
159 on construit le sd a partir de cette classe
161 - cas 2 : sd_prod est une fonction
162 on l'evalue avec les mots-cles de l'etape (mcListe)
163 on construit le sd a partir de la classe obtenue
166 sd_prod = self.definition.sd_prod
169 if type(self.definition.sd_prod) == types.FunctionType:
170 d = self.creeDictValeurs(self.mcListe)
172 # la sd_prod d'une macro a l'objet macro_etape lui meme en premier argument
173 # Comme sd_prod peut invoquer la methode typeSDProd qui ajoute
174 # les concepts produits dans self.sdprods, il faut le mettre a
175 # zero avant de l'appeler
177 sd_prod = sd_prod(*(self,), **d)
178 #except (EOFError, self.UserError):
181 except Exception as exc:
183 traceback.print_exc()
184 raise AsException("impossible d affecter un type au resultat:",
187 # on teste maintenant si la SD est reutilisee ou s'il faut la creer
188 if self.definition.reentrant != 'n' and self.reuse:
189 # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
190 # Elle sera traitee ulterieurement.
196 self.sd = sd_prod(etape=self)
197 self.typret = sd_prod
198 # Si la commande est obligatoirement reentrante et reuse n'a pas ete specifie, c'est une erreur.
199 # On ne fait rien ici. L'erreur sera traitee par la suite.
201 if self.sd is not None and not isinstance(self.sd, ASSD):
202 raise AsException("""
203 Impossible de typer le resultat !
205 Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte,
206 soit il y a une "," a la fin d'une commande precedente.
207 Developpeur : La fonction "sd_prod" retourne un type invalide.""")
210 def getType_produit(self, force=0):
212 return self.getType_produit_brut(force)
214 # traceback.print_exc()
217 def getType_produit_brut(self, force=0):
219 Retourne le type du concept resultat de l'etape et eventuellement type
220 les concepts produits "a droite" du signe egal (en entree)
223 - cas 1 : sd_prod de oper n'est pas une fonction
224 il s'agit d'une sous classe de ASSD
225 on retourne le nom de la classe
226 - cas 2 : il s'agit d'une fonction
227 on l'evalue avec les mots-cles de l'etape (mcListe)
228 et on retourne son resultat
230 if not force and hasattr(self, 'typret'):
233 if type(self.definition.sd_prod) == types.FunctionType:
234 d = self.creeDictValeurs(self.mcListe)
235 # Comme sd_prod peut invoquer la methode typeSDProd qui ajoute
236 # les concepts produits dans self.sdprods, il faut le mettre a zero
238 sd_prod = self.definition.sd_prod(*(self,), **d)
240 sd_prod = self.definition.sd_prod
243 def getContexteAvant(self, etape):
245 Retourne le dictionnaire des concepts connus avant etape
246 pour les commandes internes a la macro
247 On tient compte des commandes qui modifient le contexte
248 comme DETRUIRE ou les macros
250 # L'etape courante pour laquelle le contexte a ete calcule est
251 # memorisee dans self.index_etape_courante
252 # self.current_context.items() if isinstance(v, ASSD)])
253 d = self.current_context = self.g_context.copy()
256 # retirer les sd produites par 'etape'
257 sd_names = [sd.nom for sd in etape.getCreated_sd()]
263 # Exemple avec INCLUDE_MATERIAU appele dans une macro.
264 # Les fonctions restent uniquement dans le contexte de INCLUDE_MATERIAU,
265 # elles ne sont donc pas dans le contexte de la macro appelante.
266 # from warnings import warn
267 # warn("concept '%s' absent du contexte de %s" % (nom, self.nom),
268 # RuntimeWarning, stacklevel=2)
273 Methode qui supprime toutes les references arrières afin que
274 l'objet puisse etre correctement detruit par le garbage collector
276 N_MCCOMPO.MCCOMPO.supprime(self)
281 for concept in self.sdprods:
283 for etape in self.etapes:
286 def clean(self, netapes):
287 """Nettoie les `netapes` dernières etapes de la liste des etapes."""
288 if self.jdc.hist_etape:
290 for i in range(netapes):
291 e = self.etapes.pop()
297 del self.index_etapes[e]
299 def typeSDProd(self, co, t):
301 Cette methode a pour fonction de typer le concept co avec le type t
302 dans les conditions suivantes :
303 1. co est un concept produit de self
304 2. co est un concept libre : on le type et on l attribue a self
306 Elle enregistre egalement les concepts produits (on fait l hypothese
307 que la liste sdprods a ete correctement initialisee, vide probablement)
309 if not hasattr(co, 'etape'):
310 # Le concept vaut None probablement. On ignore l'appel
313 # On cherche a discriminer les differents cas de typage d'un concept
314 # produit par une macro qui est specifie dans un mot cle simple.
315 # On peut passer plusieurs fois par typeSDProd ce qui explique
316 # le nombre important de cas.
318 # Cas 1 : Le concept est libre. Il vient d'etre cree par CO(nom)
319 # Cas 2 : Le concept est produit par la macro. On est deja passe par typeSDProd.
320 # Cas semblable a Cas 1.
321 # Cas 3 : Le concept est produit par la macro englobante (parent). On transfere
322 # la propriete du concept de la macro parent a la macro courante (self)
323 # en verifiant que le type est valide
324 # Cas 4 : La concept est la propriete d'une etape fille. Ceci veut dire qu'on est
325 # deja passe par typeSDProd et que la propriete a ete transfere a une
326 # etape fille. Cas semblable a Cas 3.
327 # Cas 5 : Le concept est produit par une etape externe a la macro.
330 # Cas 1 : le concept est libre
331 # On l'attache a la macro et on change son type dans le type demande
332 # Recherche du mot cle simple associe au concept
333 mcs = self.getMcsWithCo(co)
335 raise AsException("""Erreur interne.
336 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
338 if not self.typeCO in mcs.definition.type:
339 raise AsException("""Erreur interne.
340 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" % (co, mcs.definition.type))
342 # affectation du bon type du concept
344 self.sdprods.append(co)
346 elif co.etape == self:
347 # Cas 2 : le concept est produit par la macro (self)
348 # On est deja passe par typeSDProd (Cas 1 ou 3).
349 # XXX Peut-il etre creer par une autre macro ?
350 # On verifie juste que c'est un vrai CO non deja type
351 # if co.etape == co._etape:
352 if co.isTypCO() == 1:
353 # Le concept a ete cree par la macro (self)
354 # On peut changer son type
357 # Le concept a ete cree par une macro parente
358 # Le type du concept doit etre coherent avec le type demande
360 if not isinstance(co, t):
361 raise AsException("""Erreur interne.
362 Le type demande (%s) et le type du concept (%s) devraient etre derives""" % (t, co.__class__))
364 self.sdprods.append(co)
366 elif co.etape == self.parent:
367 # Cas 3 : le concept est produit par la macro parente (self.parent)
368 # on transfere la propriete du concept a la macro fille
369 # et on change le type du concept comme demande
370 # Au prealable, on verifie que le concept existant (co) est une instance
371 # possible du type demande (t)
372 # Cette règle est normalement coherente avec les règles de
373 # verification des mots-cles
374 if not isinstance(co, t):
375 raise AsException("""
376 Impossible de changer le type du concept produit (%s) en (%s).
377 Le type actuel (%s) devrait etre une classe derivee du nouveau type (%s)""" % (co, t, co.__class__, t))
378 mcs = self.getMcsWithCo(co)
380 raise AsException("""Erreur interne.
381 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
383 if not self.typeCO in mcs.definition.type:
384 raise AsException("""Erreur interne.
385 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" % (co, mcs.definition.type))
387 # On ne change pas le type car il respecte la condition isinstance(co,t)
389 self.sdprods.append(co)
391 elif self.issubstep(co.etape):
392 # Cas 4 : Le concept est propriete d'une sous etape de la macro (self).
393 # On est deja passe par typeSDProd (Cas 3 ou 1).
394 # Il suffit de le mettre dans la liste des concepts produits (self.sdprods)
395 # Le type du concept et t doivent etre derives.
396 # Il n'y a aucune raison pour que la condition ne soit pas
398 if not isinstance(co, t):
399 raise AsException("""Erreur interne.
400 Le type demande (%s) et le type du concept (%s) devraient etre derives""" % (t, co.__class__))
401 self.sdprods.append(co)
404 # Cas 5 : le concept est produit par une autre etape
408 def issubstep(self, etape):
410 Cette methode retourne un entier indiquant si etape est une
411 sous etape de la macro self ou non
415 if etape in self.etapes:
417 for etap in self.etapes:
418 if etap.issubstep(etape):
422 def register(self, etape):
424 Enregistrement de etape dans le contexte de la macro : liste etapes
425 et demande d enregistrement global aupres du JDC
427 self.etapes.append(etape)
428 self.index_etapes[etape] = len(self.etapes) - 1
429 idetape = self.jdc.gRegister(etape)
434 Methode appelee dans l __init__ d un ASSD a sa creation pour
435 s enregistrer (reserve aux ASSD crees au sein d'une MACRO)
437 return self.jdc.o_register(sd)
439 def createSdprod(self, etape, nomsd):
441 Cette methode doit fabriquer le concept produit retourne
442 par l'etape etape et le nommer.
444 Elle est appelee a l'initiative de l'etape
445 pendant le processus de construction de cette etape : methode __call__
446 de la classe CMD (OPER ou MACRO)
447 Ce travail est realise par le contexte superieur (etape.parent)
448 car dans certains cas, le concept ne doit pas etre fabrique mais
449 l'etape doit simplement utiliser un concept preexistant.
450 - Cas 1 : etape.reuse != None : le concept est reutilise
451 - Cas 2 : l'etape appartient a une macro qui a declare un concept
452 de sortie qui doit etre produit par cette etape.
454 if nomsd in self.Outputs:
455 # Il s'agit d'un concept de sortie de la macro. Il ne faut pas le creer
456 # Il faut quand meme appeler la fonction sd_prod si elle existe.
457 # getType_produit le fait et donne le type attendu par la commande
458 # pour verification ulterieure.
459 sdprod = etape.getType_produit_brut()
460 sd = self.Outputs[nomsd]
461 # On verifie que le type du concept existant sd.__class__ est un sur type de celui attendu
462 # Cette règle est normalement coherente avec les règles de
463 # verification des mots-cles
464 if not issubclass(sdprod, sd.__class__):
466 "Le type du concept produit %s devrait etre une sur classe de %s" % (sd.__class__, sdprod))
467 # La propriete du concept est transferee a l'etape avec le type
468 # attendu par l'etape
471 if self.reuse == sd and etape.reuse != sd \
472 and getattr(sd, "executed", 0) == 1: # n'a pas ete pas detruit
473 raise AsException("Le concept '%s' est reentrant dans la macro-commande %s. "
474 "Il devrait donc l'etre dans %s (produit sous le nom '%s')."
475 % (sd.nom, self.nom, etape.nom, nomsd))
476 # On donne au concept le type produit par la sous commande.
477 # Le principe est le suivant : apres avoir verifie que le type deduit par la sous commande
478 # est bien coherent avec celui initialement affecte par la macro (voir ci dessus)
479 # on affecte au concept ce type car il peut etre plus precis
480 # (derive, en general)
481 sd.__class__ = sdprod
482 # On force egalement le nom stocke dans l'attribut sdnom : on lui donne le nom
483 # du concept associe a nomsd
485 # pour l'ajouter au contexte de la macro
486 self.g_context[sd.nom] = sd
487 elif etape.definition.reentrant != 'n' and etape.reuse != None:
488 # On est dans le cas d'une commande avec reutilisation d'un concept existant
489 # getSdProd fait le necessaire : verifications, associations, etc. mais ne cree
490 # pas un nouveau concept. Il retourne le concept reutilise
491 sd = etape.getSdProd()
492 # Dans le cas d'un concept nomme automatiquement : _xxx, __xxx,
493 # On force le nom stocke dans l'attribut sdnom de l'objet etape : on lui donne le nom
494 # du concept reutilise (sd ou etape.reuse c'est pareil)
495 # Ceci est indispensable pour eviter des erreurs lors des verifications des macros
496 # En effet une commande avec reutilisation d'un concept verifie que le nom de
497 # la variable a gauche du signe = est le meme que celui du concept reutilise.
498 # Lorsqu'une telle commande apparait dans une macro, on supprime
499 # cette verification.
500 if (etape.sdnom == '' or etape.sdnom[0] == '_'):
503 # On est dans le cas de la creation d'un nouveau concept
504 sd = etape.getSdProd()
506 self.NommerSdprod(sd, nomsd)
509 def NommerSdprod(self, sd, sdnom, restrict='non'):
511 Cette methode est appelee par les etapes internes de la macro.
512 La macro appelle le JDC pour valider le nommage.
513 On considère que l'espace de nom est unique et gere par le JDC.
514 Si le nom est deja utilise, l'appel lève une exception.
515 Si restrict=='non', on insère le concept dans le contexte du parent de la macro.
516 Si restrict=='oui', on insère le concept uniquement dans le contexte de la macro.
518 # Normalement, lorsqu'on appelle cette methode, on ne veut nommer que des concepts nouvellement crees.
519 # Le filtrage sur les concepts a creer ou a ne pas creer est fait dans la methode
520 # createSdprod. La seule chose a verifier apres conversion eventuelle du nom
521 # est de verifier que le nom n'est pas deja attribue. Ceci est fait en delegant
522 # au JDC par l'intermediaire du parent.
523 if sdnom in self.Outputs :
524 # Il s'agit d'un concept de sortie de la macro produit par une
526 sdnom = self.Outputs[sdnom].nom
528 if sdnom[0] in ('_', '.') and sdnom[1:].isdigit():
529 # il est deja de la forme _9000012 ou .9000017
531 elif sdnom[0] == '_':
532 # Si le nom du concept commence par le caractère '_', on lui attribue
533 # un identificateur JEVEUX construit par gcncon.
534 # nom commençant par __ : il s'agit de concepts qui seront detruits
535 # nom commençant par _ : il s'agit de concepts intermediaires
537 if len(sdnom) > 1 and sdnom[1] == '_':
538 sdnom = self.gcncon('.')
540 sdnom = self.gcncon('_')
541 elif self.nom in ('INCLUDE', 'MACR_RECAL'):
542 # dans le cas d'INCLUDE, on passe
543 # MACR_RECAL fonctionne comme INCLUDE
546 # On est dans le cas d'un nom de concept global
547 # XXX a voir, creation de CO() dans CALC_ESSAI (sdls139a)
550 "Resultat non declare par la macro %s : %s" % (self.nom, sdnom))
552 if restrict == 'non':
553 # On demande le nommage au parent mais sans ajout du concept dans le contexte du parent
554 # car on va l'ajouter dans le contexte de la macro
555 self.parent.NommerSdprod(sd, sdnom, restrict='oui')
556 # On ajoute dans le contexte de la macro les concepts nommes
557 # Ceci est indispensable pour les CO (macro) dans un INCLUDE
558 self.g_context[sdnom] = sd
560 # La demande de nommage vient probablement d'une macro qui a mis
561 # le concept dans son contexte. On ne traite plus que le nommage (restrict="oui")
562 self.parent.NommerSdprod(sd, sdnom, restrict='oui')
564 def deleteConceptAfterEtape(self, etape, sd):
566 Met a jour les etapes de la MACRO qui sont après etape suite a
567 la disparition du concept sd
569 # Cette methode est definie dans le noyau mais ne sert que pendant la phase de creation
570 # des etapes et des concepts. Il n'y a aucun traitement particulier a realiser
571 # Dans d'autres conditions, il faudrait surcharger cette methode.
574 def getCreated_sd(self):
575 """Retourne la liste des sd reellement produites par l'etape.
576 Si reuse est present, `self.sd` a ete creee avant, donc n'est pas dans
578 sdprods = self.sdprods[:]
579 if not self.reuse and self.sd:
580 sdprods.append(self.sd)
583 def getLastConcept(self):
584 """Retourne le dernier concept produit dans la macro.
585 Peut-etre utile pour acceder au contenu 'fortran' dans une
587 return self.g_context.get(self.last, None)
589 def accept(self, visitor):
591 Cette methode permet de parcourir l'arborescence des objets
592 en utilisant le pattern VISITEUR
594 visitor.visitMACRO_ETAPE(self)
596 def updateContext(self, d):
598 Met a jour le contexte contenu dans le dictionnaire d
599 Une MACRO_ETAPE peut ajouter plusieurs concepts dans le contexte
600 Une fonction enregistree dans op_init peut egalement modifier le contexte
602 if type(self.definition.op_init) == types.FunctionType:
603 self.definition.op_init(*(self, d))
605 d[self.sd.nom] = self.sd
606 for co in self.sdprods:
609 def makeInclude(self, unite=None, fname=None):
610 """Inclut un fichier dont l'unite logique est `unite` ou de nom `fname`"""
611 if unite is not None:
612 warn("'unite' is deprecated, please use 'fname' instead",
613 DeprecationWarning, stacklevel=2)
614 fname = 'fort.%s' % unite
617 f, text = self.getFile(fic_origine=self.parent.nom, fname=fname)
618 self.fichier_init = f
621 self.makeContexte(f, text)
623 def makePoursuite(self):
624 """Inclut un fichier poursuite"""
625 raise NotImplementedError('this method must be derivated (in Eficas)')
627 def makeContexte(self, f, text):
629 Interprete le texte fourni (text) issu du fichier f
630 dans le contexte du parent.
631 Cette methode est utile pour le fonctionnement des
634 # on execute le texte fourni dans le contexte forme par
635 # le contexte de l etape pere (global au sens Python)
636 # et le contexte de l etape (local au sens Python)
637 code = compile(text, f, 'exec')
638 d = self.g_context = self.macro_const_context
639 globs = self.getGlobalContexte()
642 # pour ne pas conserver des references sur tout
643 self.macro_const_context = {}
645 def getGlobalContexte(self):
647 Cette methode retourne le contexte global fourni
648 par le parent(self) a une etape fille (l'appelant) pour
649 realiser des evaluations de texte Python (INCLUDE,...)
651 # Le contexte global est forme par concatenation du contexte
652 # du parent de self et de celui de l'etape elle meme (self)
653 # Pour les concepts, cela ne doit rien changer. Mais pour les constantes,
654 # les valeurs de getContexteAvant sont moins recentes que dans
655 # getGlobalContexte. On prend donc la precaution de ne pas ecraser
657 d = self.parent.getGlobalContexte()
658 d.update(self.g_context)
659 d.update([(k, v) for k, v in list(self.parent.getContexteAvant(self).items())
660 if d.get(k) is None])
663 def getContexteCourant(self, etape_fille_du_jdc=None):
665 Retourne le contexte tel qu'il est au moment de l'execution de
669 # update car par ricochet on modifierait jdc.current_context
670 ctx.update(self.parent.getContexteCourant(self))
671 # on peut mettre None car toujours en PAR_LOT='NON', donc la dernière
672 ctx.update(self.getContexteAvant(None))
675 def getConcept(self, nomsd):
677 Methode pour recuperer un concept a partir de son nom
678 dans le contexte du jdc connu avant l'execution de la macro courante.
680 # chercher dans self.getContexteAvant, puis si non trouve
681 # self.parent.getConcept est peut-etre plus performant
682 co = self.getContexteCourant().get(nomsd.strip(), None)
683 if not isinstance(co, ASSD):
687 def getConceptByType(self, nomsd, typesd, etape=None):
689 Methode pour recuperer un concept a partir de son nom et de son type.
690 Il aura comme père 'etape' (ou la macro courante si etape est absente).
692 return self.parent.getConceptByType(nomsd, typesd, etape=etape or self)
695 """ Methode qui retourne une copie de self non enregistree auprès du JDC
697 On surcharge la methode de ETAPE pour exprimer que les concepts crees
698 par la MACRO d'origine ne sont pas crees par la copie mais eventuellement
701 etape = N_ETAPE.ETAPE.copy(self)
705 def copyIntern(self, etape):
706 """ Cette methode effectue la recopie des etapes internes d'une macro
707 passee en argument (etape)
710 self.index_etapes = {}
711 for etp in etape.etapes:
713 new_etp.copyReuse(etp)
714 new_etp.copySdnom(etp)
715 new_etp.reparent(self)
717 new_sd = etp.sd.__class__(etape=new_etp)
720 new_sd.setName(etp.sd.nom)
722 self.NommerSdprod(new_sd, etp.sd.nom)
723 new_etp.copyIntern(etp)
724 self.etapes.append(new_etp)
725 self.index_etapes[new_etp] = len(self.etapes) - 1
727 def resetJdc(self, new_jdc):
729 Reinitialise l'etape avec un nouveau jdc parent new_jdc
731 if self.sd and self.reuse == None:
732 self.parent.NommerSdprod(self.sd, self.sd.nom)
733 for concept in self.sdprods:
734 self.parent.NommerSdprod(concept, concept.nom)
736 def reparent(self, parent):
738 Cette methode sert a reinitialiser la parente de l'objet
740 N_ETAPE.ETAPE.reparent(self, parent)
741 # on ne change pas la parente des concepts. On s'assure uniquement que
742 # le jdc en reference est le bon
743 for concept in self.sdprods:
744 concept.jdc = self.jdc
745 for e in self.etapes:
748 def updateConstContext(self, d):
750 Met a jour le contexte des constantes pour l'evaluation de
751 formules dans la macro.
753 # Dans le jdc, const_context est mis a jour par execCompile
754 # Dans la macro, on n'a pas le code a compiler pour recupèrer les
755 # constantes locales a la macro. On demande donc explicitement de
756 # definir les constantes "locales".
757 self.macro_const_context.update(d)
759 def sdAccessible(self):
760 """On peut acceder aux "valeurs" (jeveux) des ASSD dans
761 les macro-commandes qui sont localement en PAR_LOT="NON"
765 print((' `- MACRO sdAccessible :', self.nom))
766 return self.parent.sdAccessible() or not self.isInclude()