2 # Copyright (C) 2007-2013 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 à vérifier et à exécuter
31 from warnings import warn
36 from N_Exception import AsException
38 from N_utils import AsType
40 from N_ASSD import ASSD
41 from N_info import message, SUPERV
44 class MACRO_ETAPE(N_ETAPE.ETAPE):
52 def __init__(self, oper=None, reuse=None, args={}):
55 - definition : objet portant les attributs de définition d'une étape
56 de type macro-commande. Il est initialisé par
58 - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc
59 en sortie si les conditions d'exécution de l'opérateur
61 - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé
64 N_ETAPE.ETAPE.__init__(self, oper, reuse, args, niveau=5)
67 self.current_context = {}
68 self.macro_const_context = {}
69 self.index_etape_courante = 0
71 self.index_etapes = {}
72 # Dans le cas d'une macro écrite en Python, l'attribut Outputs est un
73 # dictionnaire qui contient les concepts produits de sortie
74 # (nom : ASSD) déclarés dans la fonction sd_prod
77 self.UserError = "UserError"
78 # permet de stocker le nom du dernier concept nommé dans la macro
81 def make_register(self):
83 Initialise les attributs jdc, id, niveau et réalise les enregistrements
86 N_ETAPE.ETAPE.make_register(self)
88 self.UserError = self.jdc.UserError
90 self.UserError = "UserError"
92 def Build_sd(self, nom):
94 Construit le concept produit de l'opérateur. Deux cas
95 peuvent se présenter :
97 - le parent n'est pas défini. Dans ce cas, l'étape prend en charge
98 la création et le nommage du concept.
100 - le parent est défini. Dans ce cas, l'étape demande au parent la
101 création et le nommage du concept.
104 # message.debug(SUPERV, "%s", self.nom)
107 # On positionne la macro self en tant que current_step pour que les
108 # étapes créées lors de l'appel à sd_prod et à op_init aient la macro
110 self.set_current_step()
112 sd = self.parent.create_sdprod(self, nom)
113 if type(self.definition.op_init) == types.FunctionType:
114 apply(self.definition.op_init, (
115 self, self.parent.g_context))
117 sd = self.get_sd_prod()
118 if sd != None and self.reuse == None:
119 # On ne nomme le concept que dans le cas de non reutilisation
122 self.reset_current_step()
123 except AsException, e:
124 self.reset_current_step()
125 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
126 'fichier : ', self.appel[1], e)
127 except (EOFError, self.UserError):
128 # Le retablissement du step courant n'est pas strictement
129 # necessaire. On le fait pour des raisons de coherence
130 self.reset_current_step()
133 self.reset_current_step()
134 l = traceback.format_exception(
135 sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])
136 raise AsException("Etape ", self.nom, 'ligne : ', self.appel[0],
137 'fichier : ', self.appel[1] + '\n',
143 def get_sd_prod(self):
145 Retourne le concept résultat d'une macro étape
146 La difference avec une etape ou une proc-etape tient a ce que
147 le concept produit peut exister ou pas
149 Si sd_prod == None le concept produit n existe pas on retourne None
152 - cas 1 : sd_prod n'est pas une fonction
153 il s'agit d'une sous classe de ASSD
154 on construit le sd à partir de cette classe
156 - cas 2 : sd_prod est une fonction
157 on l'évalue avec les mots-clés de l'étape (mc_liste)
158 on construit le sd à partir de la classe obtenue
161 sd_prod = self.definition.sd_prod
164 if type(self.definition.sd_prod) == types.FunctionType:
165 d = self.cree_dict_valeurs(self.mc_liste)
167 # la sd_prod d'une macro a l'objet macro_etape lui meme en premier argument
168 # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute
169 # les concepts produits dans self.sdprods, il faut le mettre à
170 # zéro avant de l'appeler
172 sd_prod = apply(sd_prod, (self,), d)
173 except (EOFError, self.UserError):
177 traceback.print_exc()
178 l = traceback.format_exception(
179 sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])
181 "impossible d affecter un type au resultat\n", string.join(l[2:]))
183 # on teste maintenant si la SD est réutilisée ou s'il faut la créer
184 if self.definition.reentrant != 'n' and self.reuse:
185 # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
186 # Elle sera traitee ulterieurement.
192 self.sd = sd_prod(etape=self)
193 self.typret = sd_prod
194 # Si la commande est obligatoirement reentrante et reuse n'a pas ete specifie, c'est une erreur.
195 # On ne fait rien ici. L'erreur sera traitee par la suite.
197 if self.sd is not None and not isinstance(self.sd, ASSD):
198 raise AsException("""
199 Impossible de typer le résultat !
201 Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte,
202 soit il y a une "," à la fin d'une commande précédente.
203 Développeur : La fonction "sd_prod" retourne un type invalide.""")
206 def get_type_produit(self, force=0):
208 return self.get_type_produit_brut(force)
210 # traceback.print_exc()
213 def get_type_produit_brut(self, force=0):
215 Retourne le type du concept résultat de l'étape et eventuellement type
216 les concepts produits "à droite" du signe égal (en entrée)
219 - cas 1 : sd_prod de oper n'est pas une fonction
220 il s'agit d'une sous classe de ASSD
221 on retourne le nom de la classe
222 - cas 2 : il s'agit d'une fonction
223 on l'évalue avec les mots-clés de l'étape (mc_liste)
224 et on retourne son résultat
226 if not force and hasattr(self, 'typret'):
229 if type(self.definition.sd_prod) == types.FunctionType:
230 d = self.cree_dict_valeurs(self.mc_liste)
231 # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute
232 # les concepts produits dans self.sdprods, il faut le mettre à zéro
234 sd_prod = apply(self.definition.sd_prod, (self,), d)
236 sd_prod = self.definition.sd_prod
239 def get_contexte_avant(self, etape):
241 Retourne le dictionnaire des concepts connus avant etape
242 pour les commandes internes a la macro
243 On tient compte des commandes qui modifient le contexte
244 comme DETRUIRE ou les macros
246 # L'étape courante pour laquelle le contexte a été calculé est
247 # mémorisée dans self.index_etape_courante
248 # message.debug(SUPERV, "g_context : %s", [k for k, v in self.g_context.items() if isinstance(v, ASSD)])
249 # message.debug(SUPERV, "current_context : %s", [k for k, v in
250 # self.current_context.items() if isinstance(v, ASSD)])
251 d = self.current_context = self.g_context.copy()
254 # retirer les sd produites par 'etape'
255 sd_names = [sd.nom for sd in etape.get_created_sd()]
256 # message.debug(SUPERV, "etape: %s, reuse : %s, sdprods de %s : %s",
257 # self.nom, etape.reuse, etape.nom, sd_names)
263 # Exemple avec INCLUDE_MATERIAU appelé 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 Méthode qui supprime toutes les références arrières afin que
274 l'objet puisse etre correctement détruit 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 étapes de la liste des étapes."""
288 if self.jdc.hist_etape:
290 for i in xrange(netapes):
291 e = self.etapes.pop()
297 # message.debug(SUPERV, "MACRO.clean - etape = %s - refcount(e) = %d",
298 # e.nom, sys.getrefcount(e))
299 del self.index_etapes[e]
301 def type_sdprod(self, co, t):
303 Cette methode a pour fonction de typer le concept co avec le type t
304 dans les conditions suivantes :
305 1. co est un concept produit de self
306 2. co est un concept libre : on le type et on l attribue à self
308 Elle enregistre egalement les concepts produits (on fait l hypothese
309 que la liste sdprods a été correctement initialisee, vide probablement)
311 if not hasattr(co, 'etape'):
312 # Le concept vaut None probablement. On ignore l'appel
315 # On cherche a discriminer les differents cas de typage d'un concept
316 # produit par une macro qui est specifie dans un mot cle simple.
317 # On peut passer plusieurs fois par type_sdprod ce qui explique
318 # le nombre important de cas.
320 # Cas 1 : Le concept est libre. Il vient d'etre cree par CO(nom)
321 # Cas 2 : Le concept est produit par la macro. On est deja passe par type_sdprod.
322 # Cas semblable a Cas 1.
323 # Cas 3 : Le concept est produit par la macro englobante (parent). On transfere
324 # la propriete du concept de la macro parent a la macro courante (self)
325 # en verifiant que le type est valide
326 # Cas 4 : La concept est la propriete d'une etape fille. Ceci veut dire qu'on est
327 # deja passe par type_sdprod et que la propriete a ete transfere a une
328 # etape fille. Cas semblable a Cas 3.
329 # Cas 5 : Le concept est produit par une etape externe a la macro.
332 # Cas 1 : le concept est libre
333 # On l'attache a la macro et on change son type dans le type demande
334 # Recherche du mot cle simple associe au concept
335 mcs = self.get_mcs_with_co(co)
337 raise AsException("""Erreur interne.
338 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
340 if not self.typeCO in mcs.definition.type:
341 raise AsException("""Erreur interne.
342 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" % (co, mcs.definition.type))
344 # affectation du bon type du concept
345 # message.debug(SUPERV, "MACRO.type_sdprod : changement de type de
348 self.sdprods.append(co)
350 elif co.etape == self:
351 # Cas 2 : le concept est produit par la macro (self)
352 # On est deja passe par type_sdprod (Cas 1 ou 3).
353 # XXX Peut-il être créer par une autre macro ?
354 # On vérifie juste que c'est un vrai CO non déjà typé
355 # if co.etape == co._etape:
356 if co.is_typco() == 1:
357 # Le concept a été créé par la macro (self)
358 # On peut changer son type
361 # Le concept a été créé par une macro parente
362 # Le type du concept doit etre coherent avec le type demande
364 if not isinstance(co, t):
365 raise AsException("""Erreur interne.
366 Le type demande (%s) et le type du concept (%s) devraient etre derives""" % (t, co.__class__))
368 self.sdprods.append(co)
370 elif co.etape == self.parent:
371 # Cas 3 : le concept est produit par la macro parente (self.parent)
372 # on transfere la propriete du concept a la macro fille
373 # et on change le type du concept comme demande
374 # Au prealable, on verifie que le concept existant (co) est une instance
375 # possible du type demande (t)
376 # Cette règle est normalement cohérente avec les règles de
377 # vérification des mots-clés
378 if not isinstance(co, t):
379 raise AsException("""
380 Impossible de changer le type du concept produit (%s) en (%s).
381 Le type actuel (%s) devrait etre une classe derivee du nouveau type (%s)""" % (co, t, co.__class__, t))
382 mcs = self.get_mcs_with_co(co)
384 raise AsException("""Erreur interne.
385 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
387 if not self.typeCO in mcs.definition.type:
388 raise AsException("""Erreur interne.
389 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" % (co, mcs.definition.type))
391 # On ne change pas le type car il respecte la condition isinstance(co,t)
393 self.sdprods.append(co)
395 elif self.issubstep(co.etape):
396 # Cas 4 : Le concept est propriété d'une sous etape de la macro (self).
397 # On est deja passe par type_sdprod (Cas 3 ou 1).
398 # Il suffit de le mettre dans la liste des concepts produits (self.sdprods)
399 # Le type du concept et t doivent etre derives.
400 # Il n'y a aucune raison pour que la condition ne soit pas
402 if not isinstance(co, t):
403 raise AsException("""Erreur interne.
404 Le type demande (%s) et le type du concept (%s) devraient etre derives""" % (t, co.__class__))
405 self.sdprods.append(co)
408 # Cas 5 : le concept est produit par une autre étape
412 def issubstep(self, etape):
414 Cette methode retourne un entier indiquant si etape est une
415 sous etape de la macro self ou non
419 if etape in self.etapes:
421 for etap in self.etapes:
422 if etap.issubstep(etape):
426 def register(self, etape):
428 Enregistrement de etape dans le contexte de la macro : liste etapes
429 et demande d enregistrement global aupres du JDC
431 self.etapes.append(etape)
432 self.index_etapes[etape] = len(self.etapes) - 1
433 idetape = self.jdc.g_register(etape)
436 def reg_sd(self, sd):
438 Methode appelee dans l __init__ d un ASSD a sa creation pour
439 s enregistrer (reserve aux ASSD créés au sein d'une MACRO)
441 return self.jdc.o_register(sd)
443 def create_sdprod(self, etape, nomsd):
445 Cette methode doit fabriquer le concept produit retourne
446 par l'etape etape et le nommer.
448 Elle est appelée à l'initiative de l'etape
449 pendant le processus de construction de cette etape : methode __call__
450 de la classe CMD (OPER ou MACRO)
451 Ce travail est réalisé par le contexte supérieur (etape.parent)
452 car dans certains cas, le concept ne doit pas etre fabriqué mais
453 l'etape doit simplement utiliser un concept préexistant.
454 - Cas 1 : etape.reuse != None : le concept est réutilisé
455 - Cas 2 : l'étape appartient à une macro qui a déclaré un concept
456 de sortie qui doit etre produit par cette etape.
458 if self.Outputs.has_key(nomsd):
459 # Il s'agit d'un concept de sortie de la macro. Il ne faut pas le créer
460 # Il faut quand meme appeler la fonction sd_prod si elle existe.
461 # get_type_produit le fait et donne le type attendu par la commande
462 # pour verification ultérieure.
463 sdprod = etape.get_type_produit_brut()
464 sd = self.Outputs[nomsd]
465 # On verifie que le type du concept existant sd.__class__ est un sur type de celui attendu
466 # Cette règle est normalement cohérente avec les règles de
467 # vérification des mots-clés
468 if not issubclass(sdprod, sd.__class__):
470 "Le type du concept produit %s devrait etre une sur classe de %s" % (sd.__class__, sdprod))
471 # La propriete du concept est transferee a l'etape avec le type
472 # attendu par l'étape
475 if self.reuse == sd and etape.reuse != sd \
476 and getattr(sd, "executed", 0) == 1: # n'a pas été pas détruit
477 raise AsException("Le concept '%s' est réentrant dans la macro-commande %s. "
478 "Il devrait donc l'être dans %s (produit sous le nom '%s')."
479 % (sd.nom, self.nom, etape.nom, nomsd))
480 # On donne au concept le type produit par la sous commande.
481 # Le principe est le suivant : apres avoir verifie que le type deduit par la sous commande
482 # est bien coherent avec celui initialement affecte par la macro (voir ci dessus)
483 # on affecte au concept ce type car il peut etre plus precis
484 # (derive, en general)
485 sd.__class__ = sdprod
486 # On force également le nom stocké dans l'attribut sdnom : on lui donne le nom
487 # du concept associé à nomsd
489 # pour l'ajouter au contexte de la macro
490 self.g_context[sd.nom] = sd
491 elif etape.definition.reentrant != 'n' and etape.reuse != None:
492 # On est dans le cas d'une commande avec reutilisation d'un concept existant
493 # get_sd_prod fait le necessaire : verifications, associations, etc. mais ne cree
494 # pas un nouveau concept. Il retourne le concept reutilise
495 sd = etape.get_sd_prod()
496 # Dans le cas d'un concept nomme automatiquement : _xxx, __xxx,
497 # On force le nom stocke dans l'attribut sdnom de l'objet etape : on lui donne le nom
498 # du concept reutilise (sd ou etape.reuse c'est pareil)
499 # Ceci est indispensable pour eviter des erreurs lors des verifications des macros
500 # En effet une commande avec reutilisation d'un concept verifie que le nom de
501 # la variable a gauche du signe = est le meme que celui du concept reutilise.
502 # Lorsqu'une telle commande apparait dans une macro, on supprime
503 # cette verification.
504 if (etape.sdnom == '' or etape.sdnom[0] == '_'):
507 # On est dans le cas de la creation d'un nouveau concept
508 sd = etape.get_sd_prod()
510 self.NommerSdprod(sd, nomsd)
513 def NommerSdprod(self, sd, sdnom, restrict='non'):
515 Cette méthode est appelée par les etapes internes de la macro.
516 La macro appelle le JDC pour valider le nommage.
517 On considère que l'espace de nom est unique et géré par le JDC.
518 Si le nom est déjà utilisé, l'appel lève une exception.
519 Si restrict=='non', on insère le concept dans le contexte du parent de la macro.
520 Si restrict=='oui', on insère le concept uniquement dans le contexte de la macro.
522 # Normalement, lorsqu'on appelle cette methode, on ne veut nommer que des concepts nouvellement crees.
523 # Le filtrage sur les concepts a creer ou a ne pas creer est fait dans la methode
524 # create_sdprod. La seule chose a verifier apres conversion eventuelle du nom
525 # est de verifier que le nom n'est pas deja attribue. Ceci est fait en delegant
526 # au JDC par l'intermediaire du parent.
527 # message.debug(SUPERV, "macro results = %s, (sdnom: %r, restrict: %r)",
528 # self.Outputs.keys(), sdnom, restrict)
529 if self.Outputs.has_key(sdnom):
530 # Il s'agit d'un concept de sortie de la macro produit par une
532 sdnom = self.Outputs[sdnom].nom
534 if sdnom[0] in ('_', '.') and sdnom[1:].isdigit():
535 # il est déjà de la forme _9000012 ou .9000017
537 elif sdnom[0] == '_':
538 # Si le nom du concept commence par le caractère '_', on lui attribue
539 # un identificateur JEVEUX construit par gcncon.
540 # nom commençant par __ : il s'agit de concepts qui seront détruits
541 # nom commençant par _ : il s'agit de concepts intermediaires
543 if len(sdnom) > 1 and sdnom[1] == '_':
544 sdnom = self.gcncon('.')
546 sdnom = self.gcncon('_')
547 elif self.nom in ('INCLUDE', 'MACR_RECAL'):
548 # dans le cas d'INCLUDE, on passe
549 # MACR_RECAL fonctionne comme INCLUDE
552 # On est dans le cas d'un nom de concept global
553 # XXX à voir, création de CO() dans CALC_ESSAI (sdls139a)
554 if not sd.is_typco():
556 "Résultat non déclaré par la macro %s : %s" % (self.nom, sdnom))
558 if restrict == 'non':
559 # On demande le nommage au parent mais sans ajout du concept dans le contexte du parent
560 # car on va l'ajouter dans le contexte de la macro
561 self.parent.NommerSdprod(sd, sdnom, restrict='oui')
562 # On ajoute dans le contexte de la macro les concepts nommes
563 # Ceci est indispensable pour les CO (macro) dans un INCLUDE
564 self.g_context[sdnom] = sd
565 # message.debug(SUPERV, "g_context[%s] = %s", sdnom, sd)
567 # La demande de nommage vient probablement d'une macro qui a mis
568 # le concept dans son contexte. On ne traite plus que le nommage (restrict="oui")
569 # message.debug(SUPERV, "restrict=oui co[%s] = %s", sdnom, sd)
570 self.parent.NommerSdprod(sd, sdnom, restrict='oui')
572 def delete_concept_after_etape(self, etape, sd):
574 Met à jour les étapes de la MACRO qui sont après etape suite à
575 la disparition du concept sd
577 # Cette methode est définie dans le noyau mais ne sert que pendant la phase de creation
578 # des etapes et des concepts. Il n'y a aucun traitement particulier à réaliser
579 # Dans d'autres conditions, il faudrait surcharger cette méthode.
582 def get_created_sd(self):
583 """Retourne la liste des sd réellement produites par l'étape.
584 Si reuse est présent, `self.sd` a été créée avant, donc n'est pas dans
586 sdprods = self.sdprods[:]
587 if not self.reuse and self.sd:
588 sdprods.append(self.sd)
591 def get_last_concept(self):
592 """Retourne le dernier concept produit dans la macro.
593 Peut-être utile pour accéder au contenu 'fortran' dans une
595 return self.g_context.get(self.last, None)
597 def accept(self, visitor):
599 Cette methode permet de parcourir l'arborescence des objets
600 en utilisant le pattern VISITEUR
602 visitor.visitMACRO_ETAPE(self)
604 def update_context(self, d):
606 Met à jour le contexte contenu dans le dictionnaire d
607 Une MACRO_ETAPE peut ajouter plusieurs concepts dans le contexte
608 Une fonction enregistree dans op_init peut egalement modifier le contexte
610 if type(self.definition.op_init) == types.FunctionType:
611 apply(self.definition.op_init, (self, d))
613 d[self.sd.nom] = self.sd
614 for co in self.sdprods:
617 def make_include(self, unite=None, fname=None):
618 """Inclut un fichier dont l'unite logique est `unite` ou de nom `fname`"""
619 if unite is not None:
620 warn("'unite' is deprecated, please use 'fname' instead",
621 DeprecationWarning, stacklevel=2)
622 fname = 'fort.%s' % unite
625 f, text = self.get_file(fic_origine=self.parent.nom, fname=fname)
626 self.fichier_init = f
629 self.make_contexte(f, text)
631 def make_poursuite(self):
632 """Inclut un fichier poursuite"""
633 raise NotImplementedError('this method must be derivated (in Eficas)')
635 def make_contexte(self, f, text):
637 Interprete le texte fourni (text) issu du fichier f
638 dans le contexte du parent.
639 Cette methode est utile pour le fonctionnement des
642 # on execute le texte fourni dans le contexte forme par
643 # le contexte de l etape pere (global au sens Python)
644 # et le contexte de l etape (local au sens Python)
645 code = compile(text, f, 'exec')
646 d = self.g_context = self.macro_const_context
647 globs = self.get_global_contexte()
649 exec code in globs, d
650 # pour ne pas conserver des références sur tout
651 self.macro_const_context = {}
653 def get_global_contexte(self):
655 Cette methode retourne le contexte global fourni
656 par le parent(self) a une etape fille (l'appelant) pour
657 realiser des evaluations de texte Python (INCLUDE,...)
659 # Le contexte global est forme par concatenation du contexte
660 # du parent de self et de celui de l'etape elle meme (self)
661 # Pour les concepts, cela ne doit rien changer. Mais pour les constantes,
662 # les valeurs de get_contexte_avant sont moins récentes que dans
663 # get_global_contexte. On prend donc la précaution de ne pas écraser
665 d = self.parent.get_global_contexte()
666 d.update(self.g_context)
667 d.update([(k, v) for k, v in self.parent.get_contexte_avant(self).items()
668 if d.get(k) is None])
671 def get_contexte_courant(self, etape_fille_du_jdc=None):
673 Retourne le contexte tel qu'il est au moment de l'exécution de
677 # update car par ricochet on modifierait jdc.current_context
678 ctx.update(self.parent.get_contexte_courant(self))
679 # on peut mettre None car toujours en PAR_LOT='NON', donc la dernière
680 ctx.update(self.get_contexte_avant(None))
683 def get_concept(self, nomsd):
685 Méthode pour recuperer un concept à partir de son nom
686 dans le contexte du jdc connu avant l'exécution de la macro courante.
688 # chercher dans self.get_contexte_avant, puis si non trouve
689 # self.parent.get_concept est peut-etre plus performant
690 co = self.get_contexte_courant().get(nomsd.strip(), None)
691 if not isinstance(co, ASSD):
695 def get_concept_by_type(self, nomsd, typesd, etape=None):
697 Méthode pour récuperer un concept à partir de son nom et de son type.
698 Il aura comme père 'etape' (ou la macro courante si etape est absente).
700 return self.parent.get_concept_by_type(nomsd, typesd, etape=etape or self)
703 """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
705 On surcharge la methode de ETAPE pour exprimer que les concepts crees
706 par la MACRO d'origine ne sont pas crees par la copie mais eventuellement
709 etape = N_ETAPE.ETAPE.copy(self)
713 def copy_intern(self, etape):
714 """ Cette méthode effectue la recopie des etapes internes d'une macro
715 passée en argument (etape)
718 self.index_etapes = {}
719 for etp in etape.etapes:
721 new_etp.copy_reuse(etp)
722 new_etp.copy_sdnom(etp)
723 new_etp.reparent(self)
725 new_sd = etp.sd.__class__(etape=new_etp)
728 new_sd.set_name(etp.sd.nom)
730 self.NommerSdprod(new_sd, etp.sd.nom)
731 new_etp.copy_intern(etp)
732 self.etapes.append(new_etp)
733 self.index_etapes[new_etp] = len(self.etapes) - 1
735 def reset_jdc(self, new_jdc):
737 Reinitialise l'etape avec un nouveau jdc parent new_jdc
739 if self.sd and self.reuse == None:
740 self.parent.NommerSdprod(self.sd, self.sd.nom)
741 for concept in self.sdprods:
742 self.parent.NommerSdprod(concept, concept.nom)
744 def reparent(self, parent):
746 Cette methode sert a reinitialiser la parente de l'objet
748 N_ETAPE.ETAPE.reparent(self, parent)
749 # on ne change pas la parenté des concepts. On s'assure uniquement que
750 # le jdc en référence est le bon
751 for concept in self.sdprods:
752 concept.jdc = self.jdc
753 for e in self.etapes:
756 def update_const_context(self, d):
758 Met à jour le contexte des constantes pour l'évaluation de
759 formules dans la macro.
761 # Dans le jdc, const_context est mis à jour par exec_compile
762 # Dans la macro, on n'a pas le code à compiler pour récupèrer les
763 # constantes locales à la macro. On demande donc explicitement de
764 # définir les constantes "locales".
765 self.macro_const_context.update(d)
767 def sd_accessible(self):
768 """On peut acceder aux "valeurs" (jeveux) des ASSD dans
769 les macro-commandes qui sont localement en PAR_LOT="NON"
773 print ' `- MACRO sd_accessible :', self.nom
774 return self.parent.sd_accessible() or not self.is_include()