1 # -*- coding: iso-8859-1 -*-
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
27 import types,sys,string
29 from warnings import warn
34 from N_Exception import AsException
36 from N_utils import AsType
38 from N_ASSD import ASSD
39 from N_info import message, SUPERV
41 class MACRO_ETAPE(N_ETAPE.ETAPE):
47 def __init__(self,oper=None,reuse=None,args={}):
50 - definition : objet portant les attributs de définition d'une étape
51 de type macro-commande. Il est initialisé par
53 - reuse : indique le concept d'entrée réutilisé. Il se trouvera donc
54 en sortie si les conditions d'exécution de l'opérateur
56 - valeur : arguments d'entrée de type mot-clé=valeur. Initialisé
59 N_ETAPE.ETAPE.__init__(self, oper, reuse, args, niveau=5)
62 self.current_context = {}
63 self.macro_const_context = {}
64 self.index_etape_courante = 0
66 self.index_etapes = {}
67 # Dans le cas d'une macro écrite en Python, l'attribut Outputs est un
68 # dictionnaire qui contient les concepts produits de sortie
69 # (nom : ASSD) déclarés dans la fonction sd_prod
72 self.UserError = "UserError"
73 # permet de stocker le nom du dernier concept nommé dans la macro
76 def make_register(self):
78 Initialise les attributs jdc, id, niveau et réalise les enregistrements
81 N_ETAPE.ETAPE.make_register(self)
83 self.UserError=self.jdc.UserError
85 self.UserError="UserError"
87 def Build_sd(self,nom):
89 Construit le concept produit de l'opérateur. Deux cas
90 peuvent se présenter :
92 - le parent n'est pas défini. Dans ce cas, l'étape prend en charge
93 la création et le nommage du concept.
95 - le parent est défini. Dans ce cas, l'étape demande au parent la
96 création et le nommage du concept.
99 #message.debug(SUPERV, "%s", self.nom)
102 # On positionne la macro self en tant que current_step pour que les
103 # étapes créées lors de l'appel à sd_prod et à op_init aient la macro
105 self.set_current_step()
107 sd= self.parent.create_sdprod(self,nom)
108 if type(self.definition.op_init) == types.FunctionType:
109 apply(self.definition.op_init,(self,self.parent.g_context))
111 sd=self.get_sd_prod()
112 if sd != None and self.reuse == None:
113 # On ne nomme le concept que dans le cas de non reutilisation
116 self.reset_current_step()
117 except AsException,e:
118 self.reset_current_step()
119 raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
120 'fichier : ',self.appel[1],e)
121 except (EOFError, self.UserError):
122 # Le retablissement du step courant n'est pas strictement necessaire. On le fait pour des raisons de coherence
123 self.reset_current_step()
126 self.reset_current_step()
127 l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
128 raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
129 'fichier : ',self.appel[1]+'\n',
135 def get_sd_prod(self):
137 Retourne le concept résultat d'une macro étape
138 La difference avec une etape ou une proc-etape tient a ce que
139 le concept produit peut exister ou pas
141 Si sd_prod == None le concept produit n existe pas on retourne None
144 - cas 1 : sd_prod n'est pas une fonction
145 il s'agit d'une sous classe de ASSD
146 on construit le sd à partir de cette classe
148 - cas 2 : sd_prod est une fonction
149 on l'évalue avec les mots-clés de l'étape (mc_liste)
150 on construit le sd à partir de la classe obtenue
153 sd_prod=self.definition.sd_prod
156 if type(self.definition.sd_prod) == types.FunctionType:
157 d=self.cree_dict_valeurs(self.mc_liste)
159 # la sd_prod d'une macro a l'objet macro_etape lui meme en premier argument
160 # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute
161 # les concepts produits dans self.sdprods, il faut le mettre à zéro avant de l'appeler
163 sd_prod= apply(sd_prod,(self,),d)
164 except (EOFError,self.UserError):
167 if CONTEXT.debug: traceback.print_exc()
168 l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
169 raise AsException("impossible d affecter un type au resultat\n",string.join(l[2:]))
171 # on teste maintenant si la SD est réutilisée ou s'il faut la créer
172 if self.definition.reentrant != 'n' and self.reuse:
173 # Le concept produit est specifie reutilise (reuse=xxx). C'est une erreur mais non fatale.
174 # Elle sera traitee ulterieurement.
180 self.sd= sd_prod(etape=self)
182 # Si la commande est obligatoirement reentrante et reuse n'a pas ete specifie, c'est une erreur.
183 # On ne fait rien ici. L'erreur sera traitee par la suite.
185 if self.sd is not None and not isinstance(self.sd, ASSD):
186 raise AsException("""
187 Impossible de typer le résultat !
189 Utilisateur : Soit la valeur fournie derrière "reuse" est incorrecte,
190 soit il y a une "," à la fin d'une commande précédente.
191 Développeur : La fonction "sd_prod" retourne un type invalide.""")
194 def get_type_produit(self,force=0):
196 return self.get_type_produit_brut(force)
198 #traceback.print_exc()
201 def get_type_produit_brut(self,force=0):
203 Retourne le type du concept résultat de l'étape et eventuellement type
204 les concepts produits "à droite" du signe égal (en entrée)
207 - cas 1 : sd_prod de oper n'est pas une fonction
208 il s'agit d'une sous classe de ASSD
209 on retourne le nom de la classe
210 - cas 2 : il s'agit d'une fonction
211 on l'évalue avec les mots-clés de l'étape (mc_liste)
212 et on retourne son résultat
214 if not force and hasattr(self,'typret'):
217 if type(self.definition.sd_prod) == types.FunctionType:
218 d=self.cree_dict_valeurs(self.mc_liste)
219 # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute
220 # les concepts produits dans self.sdprods, il faut le mettre à zéro
222 sd_prod= apply(self.definition.sd_prod,(self,),d)
224 sd_prod=self.definition.sd_prod
227 def get_contexte_avant(self,etape):
229 Retourne le dictionnaire des concepts connus avant etape
230 pour les commandes internes a la macro
231 On tient compte des commandes qui modifient le contexte
232 comme DETRUIRE ou les macros
234 # L'étape courante pour laquelle le contexte a été calculé est
235 # mémorisée dans self.index_etape_courante
236 #message.debug(SUPERV, "g_context : %s", [k for k, v in self.g_context.items() if isinstance(v, ASSD)])
237 #message.debug(SUPERV, "current_context : %s", [k for k, v in self.current_context.items() if isinstance(v, ASSD)])
238 d = self.current_context = self.g_context.copy()
241 # retirer les sd produites par 'etape'
242 sd_names = [sd.nom for sd in etape.get_created_sd()]
243 #message.debug(SUPERV, "etape: %s, reuse : %s, sdprods de %s : %s",
244 #self.nom, etape.reuse, etape.nom, sd_names)
250 # Exemple avec INCLUDE_MATERIAU appelé dans une macro.
251 # Les fonctions restent uniquement dans le contexte de INCLUDE_MATERIAU,
252 # elles ne sont donc pas dans le contexte de la macro appelante.
253 #from warnings import warn
254 #warn("concept '%s' absent du contexte de %s" % (nom, self.nom),
255 #RuntimeWarning, stacklevel=2)
260 Méthode qui supprime toutes les références arrières afin que
261 l'objet puisse etre correctement détruit par le garbage collector
263 N_MCCOMPO.MCCOMPO.supprime(self)
266 if self.sd : self.sd.supprime()
267 for concept in self.sdprods:
269 for etape in self.etapes:
272 def clean(self, netapes):
273 """Nettoie les `netapes` dernières étapes de la liste des étapes."""
274 if self.jdc.hist_etape:
276 for i in xrange(netapes):
283 #message.debug(SUPERV, "MACRO.clean - etape = %s - refcount(e) = %d",
284 #e.nom, sys.getrefcount(e))
285 del self.index_etapes[e]
287 def type_sdprod(self,co,t):
289 Cette methode a pour fonction de typer le concept co avec le type t
290 dans les conditions suivantes :
291 1. co est un concept produit de self
292 2. co est un concept libre : on le type et on l attribue à self
294 Elle enregistre egalement les concepts produits (on fait l hypothese
295 que la liste sdprods a été correctement initialisee, vide probablement)
297 if not hasattr(co,'etape'):
298 # Le concept vaut None probablement. On ignore l'appel
301 # On cherche a discriminer les differents cas de typage d'un concept
302 # produit par une macro qui est specifie dans un mot cle simple.
303 # On peut passer plusieurs fois par type_sdprod ce qui explique
304 # le nombre important de cas.
306 # Cas 1 : Le concept est libre. Il vient d'etre cree par CO(nom)
307 # Cas 2 : Le concept est produit par la macro. On est deja passe par type_sdprod.
308 # Cas semblable a Cas 1.
309 # Cas 3 : Le concept est produit par la macro englobante (parent). On transfere
310 # la propriete du concept de la macro parent a la macro courante (self)
311 # en verifiant que le type est valide
312 # Cas 4 : La concept est la propriete d'une etape fille. Ceci veut dire qu'on est
313 # deja passe par type_sdprod et que la propriete a ete transfere a une
314 # etape fille. Cas semblable a Cas 3.
315 # Cas 5 : Le concept est produit par une etape externe a la macro.
318 # Cas 1 : le concept est libre
319 # On l'attache a la macro et on change son type dans le type demande
320 # Recherche du mot cle simple associe au concept
321 mcs=self.get_mcs_with_co(co)
323 raise AsException("""Erreur interne.
324 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
326 if not self.typeCO in mcs.definition.type:
327 raise AsException("""Erreur interne.
328 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type))
330 # affectation du bon type du concept
331 #message.debug(SUPERV, "MACRO.type_sdprod : changement de type de %s --> %s", co, t)
333 self.sdprods.append(co)
335 elif co.etape == self:
336 # Cas 2 : le concept est produit par la macro (self)
337 # On est deja passe par type_sdprod (Cas 1 ou 3).
338 #XXX Peut-il être créer par une autre macro ?
339 # On vérifie juste que c'est un vrai CO non déjà typé
340 #if co.etape == co._etape:
341 if co.is_typco() == 1:
342 #Le concept a été créé par la macro (self)
343 #On peut changer son type
346 #Le concept a été créé par une macro parente
347 # Le type du concept doit etre coherent avec le type demande (seulement derive)
348 if not isinstance(co,t):
349 raise AsException("""Erreur interne.
350 Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__))
352 self.sdprods.append(co)
354 elif co.etape== self.parent:
355 # Cas 3 : le concept est produit par la macro parente (self.parent)
356 # on transfere la propriete du concept a la macro fille
357 # et on change le type du concept comme demande
358 # Au prealable, on verifie que le concept existant (co) est une instance
359 # possible du type demande (t)
360 # Cette règle est normalement cohérente avec les règles de vérification des mots-clés
361 if not isinstance(co,t):
362 raise AsException("""
363 Impossible de changer le type du concept produit (%s) en (%s).
364 Le type actuel (%s) devrait etre une classe derivee du nouveau type (%s)""" % (co,t,co.__class__,t))
365 mcs=self.get_mcs_with_co(co)
367 raise AsException("""Erreur interne.
368 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
370 if not self.typeCO in mcs.definition.type:
371 raise AsException("""Erreur interne.
372 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type))
374 # On ne change pas le type car il respecte la condition isinstance(co,t)
376 self.sdprods.append(co)
378 elif self.issubstep(co.etape):
379 # Cas 4 : Le concept est propriété d'une sous etape de la macro (self).
380 # On est deja passe par type_sdprod (Cas 3 ou 1).
381 # Il suffit de le mettre dans la liste des concepts produits (self.sdprods)
382 # Le type du concept et t doivent etre derives.
383 # Il n'y a aucune raison pour que la condition ne soit pas verifiee.
384 if not isinstance(co,t):
385 raise AsException("""Erreur interne.
386 Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__))
387 self.sdprods.append(co)
390 # Cas 5 : le concept est produit par une autre étape
394 def issubstep(self,etape):
396 Cette methode retourne un entier indiquant si etape est une
397 sous etape de la macro self ou non
401 if etape in self.etapes:return 1
402 for etap in self.etapes:
403 if etap.issubstep(etape):return 1
406 def register(self,etape):
408 Enregistrement de etape dans le contexte de la macro : liste etapes
409 et demande d enregistrement global aupres du JDC
411 self.etapes.append(etape)
412 self.index_etapes[etape] = len(self.etapes) - 1
413 idetape=self.jdc.g_register(etape)
418 Methode appelee dans l __init__ d un ASSD a sa creation pour
419 s enregistrer (reserve aux ASSD créés au sein d'une MACRO)
421 return self.jdc.o_register(sd)
423 def create_sdprod(self,etape,nomsd):
425 Cette methode doit fabriquer le concept produit retourne
426 par l'etape etape et le nommer.
428 Elle est appelée à l'initiative de l'etape
429 pendant le processus de construction de cette etape : methode __call__
430 de la classe CMD (OPER ou MACRO)
431 Ce travail est réalisé par le contexte supérieur (etape.parent)
432 car dans certains cas, le concept ne doit pas etre fabriqué mais
433 l'etape doit simplement utiliser un concept préexistant.
434 - Cas 1 : etape.reuse != None : le concept est réutilisé
435 - Cas 2 : l'étape appartient à une macro qui a déclaré un concept
436 de sortie qui doit etre produit par cette etape.
438 if self.Outputs.has_key(nomsd):
439 # Il s'agit d'un concept de sortie de la macro. Il ne faut pas le créer
440 # Il faut quand meme appeler la fonction sd_prod si elle existe.
441 # get_type_produit le fait et donne le type attendu par la commande pour verification ultérieure.
442 sdprod=etape.get_type_produit_brut()
443 sd=self.Outputs[nomsd]
444 # On verifie que le type du concept existant sd.__class__ est un sur type de celui attendu
445 # Cette règle est normalement cohérente avec les règles de vérification des mots-clés
446 if not issubclass(sdprod,sd.__class__):
447 raise AsException("Le type du concept produit %s devrait etre une sur classe de %s" %(sd.__class__,sdprod))
448 # La propriete du concept est transferee a l'etape avec le type attendu par l'étape
451 if self.reuse == sd and etape.reuse != sd \
452 and getattr(sd, "executed", 0) == 1: # n'a pas été pas détruit
453 raise AsException("Le concept '%s' est réentrant dans la macro-commande %s. " \
454 "Il devrait donc l'être dans %s (produit sous le nom '%s')." \
455 % (sd.nom, self.nom, etape.nom, nomsd))
456 # On donne au concept le type produit par la sous commande.
457 # Le principe est le suivant : apres avoir verifie que le type deduit par la sous commande
458 # est bien coherent avec celui initialement affecte par la macro (voir ci dessus)
459 # on affecte au concept ce type car il peut etre plus precis (derive, en general)
461 # On force également le nom stocké dans l'attribut sdnom : on lui donne le nom
462 # du concept associé à nomsd
464 # pour l'ajouter au contexte de la macro
465 self.g_context[sd.nom] = sd
466 elif etape.definition.reentrant != 'n' and etape.reuse != None:
467 # On est dans le cas d'une commande avec reutilisation d'un concept existant
468 # get_sd_prod fait le necessaire : verifications, associations, etc. mais ne cree
469 # pas un nouveau concept. Il retourne le concept reutilise
470 sd= etape.get_sd_prod()
471 # Dans le cas d'un concept nomme automatiquement : _xxx, __xxx,
472 # On force le nom stocke dans l'attribut sdnom de l'objet etape : on lui donne le nom
473 # du concept reutilise (sd ou etape.reuse c'est pareil)
474 # Ceci est indispensable pour eviter des erreurs lors des verifications des macros
475 # En effet une commande avec reutilisation d'un concept verifie que le nom de
476 # la variable a gauche du signe = est le meme que celui du concept reutilise.
477 # Lorsqu'une telle commande apparait dans une macro, on supprime cette verification.
478 if (etape.sdnom == '' or etape.sdnom[0] == '_'):
481 # On est dans le cas de la creation d'un nouveau concept
482 sd= etape.get_sd_prod()
484 self.NommerSdprod(sd,nomsd)
487 def NommerSdprod(self,sd,sdnom,restrict='non'):
489 Cette méthode est appelée par les etapes internes de la macro.
490 La macro appelle le JDC pour valider le nommage.
491 On considère que l'espace de nom est unique et géré par le JDC.
492 Si le nom est déjà utilisé, l'appel lève une exception.
493 Si restrict=='non', on insère le concept dans le contexte du parent de la macro.
494 Si restrict=='oui', on insère le concept uniquement dans le contexte de la macro.
496 # Normalement, lorsqu'on appelle cette methode, on ne veut nommer que des concepts nouvellement crees.
497 # Le filtrage sur les concepts a creer ou a ne pas creer est fait dans la methode
498 # create_sdprod. La seule chose a verifier apres conversion eventuelle du nom
499 # est de verifier que le nom n'est pas deja attribue. Ceci est fait en delegant
500 # au JDC par l'intermediaire du parent.
501 #message.debug(SUPERV, "macro results = %s, (sdnom: %r, restrict: %r)",
502 #self.Outputs.keys(), sdnom, restrict)
503 if self.Outputs.has_key(sdnom):
504 # Il s'agit d'un concept de sortie de la macro produit par une sous commande
505 sdnom = self.Outputs[sdnom].nom
507 if sdnom[0] in ('_', '.') and sdnom[1:].isdigit():
508 # il est déjà de la forme _9000012 ou .9000017
510 elif sdnom[0] == '_':
511 # Si le nom du concept commence par le caractère '_', on lui attribue
512 # un identificateur JEVEUX construit par gcncon.
513 # nom commençant par __ : il s'agit de concepts qui seront détruits
514 # nom commençant par _ : il s'agit de concepts intermediaires qui seront gardés
515 if len(sdnom) > 1 and sdnom[1] == '_':
516 sdnom = self.gcncon('.')
518 sdnom = self.gcncon('_')
519 elif self.nom in ('INCLUDE', 'MACR_RECAL'):
520 # dans le cas d'INCLUDE, on passe
521 # MACR_RECAL fonctionne comme INCLUDE
524 # On est dans le cas d'un nom de concept global
525 #XXX à voir, création de CO() dans CALC_ESSAI (sdls139a)
526 if not sd.is_typco():
527 raise AsException("Résultat non déclaré par la macro %s : %s" % (self.nom, sdnom))
529 if restrict == 'non':
530 # On demande le nommage au parent mais sans ajout du concept dans le contexte du parent
531 # car on va l'ajouter dans le contexte de la macro
532 self.parent.NommerSdprod(sd,sdnom,restrict='oui')
533 # On ajoute dans le contexte de la macro les concepts nommes
534 # Ceci est indispensable pour les CO (macro) dans un INCLUDE
535 self.g_context[sdnom]=sd
536 #message.debug(SUPERV, "g_context[%s] = %s", sdnom, sd)
538 # La demande de nommage vient probablement d'une macro qui a mis
539 # le concept dans son contexte. On ne traite plus que le nommage (restrict="oui")
540 #message.debug(SUPERV, "restrict=oui co[%s] = %s", sdnom, sd)
541 self.parent.NommerSdprod(sd,sdnom,restrict='oui')
543 def delete_concept_after_etape(self,etape,sd):
545 Met à jour les étapes de la MACRO qui sont après etape suite à
546 la disparition du concept sd
548 # Cette methode est définie dans le noyau mais ne sert que pendant la phase de creation
549 # des etapes et des concepts. Il n'y a aucun traitement particulier à réaliser
550 # Dans d'autres conditions, il faudrait surcharger cette méthode.
553 def get_created_sd(self):
554 """Retourne la liste des sd réellement produites par l'étape.
555 Si reuse est présent, `self.sd` a été créée avant, donc n'est pas dans
557 sdprods = self.sdprods[:]
558 if not self.reuse and self.sd:
559 sdprods.append(self.sd)
562 def get_last_concept(self):
563 """Retourne le dernier concept produit dans la macro.
564 Peut-être utile pour accéder au contenu 'fortran' dans une
566 return self.g_context.get(self.last, None)
568 def accept(self,visitor):
570 Cette methode permet de parcourir l'arborescence des objets
571 en utilisant le pattern VISITEUR
573 visitor.visitMACRO_ETAPE(self)
575 def update_context(self,d):
577 Met à jour le contexte contenu dans le dictionnaire d
578 Une MACRO_ETAPE peut ajouter plusieurs concepts dans le contexte
579 Une fonction enregistree dans op_init peut egalement modifier le contexte
581 if type(self.definition.op_init) == types.FunctionType:
582 apply(self.definition.op_init,(self,d))
583 if self.sd != None:d[self.sd.nom]=self.sd
584 for co in self.sdprods:
587 def make_include(self, unite=None, fname=None):
588 """Inclut un fichier dont l'unite logique est `unite` ou de nom `fname`"""
589 if unite is not None:
590 warn("'unite' is deprecated, please use 'fname' instead",
591 DeprecationWarning, stacklevel=2)
592 fname = 'fort.%s' % unite
595 f, text = self.get_file(fic_origine=self.parent.nom, fname=fname)
596 self.fichier_init = f
599 self.make_contexte(f, text)
601 def make_poursuite(self):
602 """Inclut un fichier poursuite"""
603 raise NotImplementedError('this method must be derivated (in Eficas)')
605 def make_contexte(self,f,text):
607 Interprete le texte fourni (text) issu du fichier f
608 dans le contexte du parent.
609 Cette methode est utile pour le fonctionnement des
612 # on execute le texte fourni dans le contexte forme par
613 # le contexte de l etape pere (global au sens Python)
614 # et le contexte de l etape (local au sens Python)
615 code = compile(text,f,'exec')
616 d = self.g_context = self.macro_const_context
617 globs = self.get_global_contexte()
619 exec code in globs, d
620 # pour ne pas conserver des références sur tout
621 self.macro_const_context = {}
623 def get_global_contexte(self):
625 Cette methode retourne le contexte global fourni
626 par le parent(self) a une etape fille (l'appelant) pour
627 realiser des evaluations de texte Python (INCLUDE,...)
629 # Le contexte global est forme par concatenation du contexte
630 # du parent de self et de celui de l'etape elle meme (self)
631 # Pour les concepts, cela ne doit rien changer. Mais pour les constantes,
632 # les valeurs de get_contexte_avant sont moins récentes que dans
633 # get_global_contexte. On prend donc la précaution de ne pas écraser
635 d = self.parent.get_global_contexte()
636 d.update( self.g_context )
637 d.update( [(k, v) for k, v in self.parent.get_contexte_avant(self).items()
638 if d.get(k) is None] )
641 def get_contexte_courant(self, etape_fille_du_jdc=None):
643 Retourne le contexte tel qu'il est au moment de l'exécution de
647 # update car par ricochet on modifierait jdc.current_context
648 ctx.update( self.parent.get_contexte_courant(self) )
649 # on peut mettre None car toujours en PAR_LOT='NON', donc la dernière
650 ctx.update( self.get_contexte_avant(None) )
653 def get_concept(self, nomsd):
655 Méthode pour recuperer un concept à partir de son nom
656 dans le contexte du jdc connu avant l'exécution de la macro courante.
658 # chercher dans self.get_contexte_avant, puis si non trouve
659 # self.parent.get_concept est peut-etre plus performant
660 co = self.get_contexte_courant().get(nomsd.strip(), None)
661 if not isinstance(co, ASSD):
665 def get_concept_by_type(self, nomsd, typesd, etape=None):
667 Méthode pour récuperer un concept à partir de son nom et de son type.
668 Il aura comme père 'etape' (ou la macro courante si etape est absente).
670 return self.parent.get_concept_by_type(nomsd, typesd, etape=etape or self)
673 """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
675 On surcharge la methode de ETAPE pour exprimer que les concepts crees
676 par la MACRO d'origine ne sont pas crees par la copie mais eventuellement
679 etape=N_ETAPE.ETAPE.copy(self)
683 def copy_intern(self,etape):
684 """ Cette méthode effectue la recopie des etapes internes d'une macro
685 passée en argument (etape)
689 for etp in etape.etapes:
691 new_etp.copy_reuse(etp)
692 new_etp.copy_sdnom(etp)
693 new_etp.reparent(self)
695 new_sd = etp.sd.__class__(etape=new_etp)
698 new_sd.set_name(etp.sd.nom)
700 self.NommerSdprod(new_sd,etp.sd.nom)
701 new_etp.copy_intern(etp)
702 self.etapes.append(new_etp)
703 self.index_etapes[new_etp] = len(self.etapes) - 1
706 def reset_jdc(self,new_jdc):
708 Reinitialise l'etape avec un nouveau jdc parent new_jdc
710 if self.sd and self.reuse == None :
711 self.parent.NommerSdprod(self.sd,self.sd.nom)
712 for concept in self.sdprods:
713 self.parent.NommerSdprod(concept,concept.nom)
715 def reparent(self,parent):
717 Cette methode sert a reinitialiser la parente de l'objet
719 N_ETAPE.ETAPE.reparent(self,parent)
720 #on ne change pas la parenté des concepts. On s'assure uniquement que le jdc en référence est le bon
721 for concept in self.sdprods:
723 for e in self.etapes:
726 def update_const_context(self, d):
728 Met à jour le contexte des constantes pour l'évaluation de
729 formules dans la macro.
731 # Dans le jdc, const_context est mis à jour par exec_compile
732 # Dans la macro, on n'a pas le code à compiler pour récupèrer les
733 # constantes locales à la macro. On demande donc explicitement de
734 # définir les constantes "locales".
735 self.macro_const_context.update(d)
737 def sd_accessible(self):
738 """On peut acceder aux "valeurs" (jeveux) des ASSD dans
739 les macro-commandes qui sont localement en PAR_LOT="NON"
742 if CONTEXT.debug: print ' `- MACRO sd_accessible :', self.nom
743 return self.parent.sd_accessible() or not self.is_include()