1 #@ MODIF ops Cata DATE 16/05/2007 AUTEUR COURTOIS M.COURTOIS
2 # -*- coding: iso-8859-1 -*-
3 # CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2001 EDF R&D WWW.CODE-ASTER.ORG
6 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
7 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
8 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
9 # (AT YOUR OPTION) ANY LATER VERSION.
11 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
12 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
13 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
14 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
16 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
17 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
18 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
19 # ======================================================================
24 import string,linecache,os,traceback,re
29 from Accas import ASSD
30 from Noyau.ascheckers import CheckLog
35 # Si le module aster est présent, on le connecte
38 Build.B_CODE.CODE.codex=aster
40 from Utilitai.Utmess import UTMESS
41 from Utilitai.as_timer import ASTER_TIMER
42 from Macro.Sensibilite import MEMORISATION_SENSIBILITE
47 def commun_DEBUT_POURSUITE(jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG):
48 """Fonction sdprod partie commune à DEBUT et POURSUITE.
49 (on stocke un entier au lieu du logique)
52 jdc.impr_macro = int(IMPR_MACRO == 'OUI')
53 jdc.jxveri = int(DEBUG != None and DEBUG['JXVERI'] == 'OUI')
54 jdc.sdveri = int(DEBUG != None and DEBUG['SDVERI'] == 'OUI')
56 jdc.sd_checker = CheckLog()
58 jdc.fico = CODE['NOM']
60 jdc.timer = ASTER_TIMER(format='aster')
61 # en POURSUITE, ne pas écraser la mémorisation existante.
62 if not hasattr(jdc, 'memo_sensi'):
63 jdc.memo_sensi = MEMORISATION_SENSIBILITE()
66 def DEBUT(self,PAR_LOT,IMPR_MACRO,CODE,DEBUG,**args):
68 Fonction sdprod de la macro DEBUT
70 # La commande DEBUT ne peut exister qu'au niveau jdc
71 if self.jdc is not self.parent :
72 raise Accas.AsException("La commande DEBUT ne peut exister qu'au niveau jdc")
74 commun_DEBUT_POURSUITE(self.jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG)
77 def build_debut(self,**args):
79 Fonction ops pour la macro DEBUT
81 self.jdc.UserError=self.codex.error
83 if self.jdc.par_lot == 'NON' :
85 # On execute la fonction debut pour initialiser les bases
86 # Cette execution est indispensable avant toute autre action sur ASTER
87 # op doit etre un entier car la fonction debut appelle GCECDU qui demande
88 # le numero de l'operateur associé (getoper)
91 lot,ier=self.codex.debut(self,1)
92 # On remet op a None juste apres pour eviter que la commande DEBUT
93 # ne soit executée dans la phase d'execution
94 self.definition.op=None
97 def POURSUITE(self,PAR_LOT,IMPR_MACRO,CODE,DEBUG,**args):
99 Fonction sdprod de la macro POURSUITE
101 # La commande POURSUITE ne peut exister qu'au niveau jdc
102 if self.jdc is not self.parent :
103 raise Accas.AsException("La commande POURSUITE ne peut exister qu'au niveau jdc")
105 commun_DEBUT_POURSUITE(self.jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG)
107 if (self.codex and os.path.isfile("glob.1") or os.path.isfile("bhdf.1")):
108 # Le module d'execution est accessible et glob.1 est present
109 # Pour eviter de rappeler plusieurs fois la sequence d'initialisation
110 # on memorise avec l'attribut fichier_init que l'initialisation
112 if hasattr(self,'fichier_init'):return
113 self.fichier_init='glob.1'
115 # le sous programme fortran appelé par self.codex.poursu demande le numero
116 # de l'operateur (GCECDU->getoper), on lui donne la valeur 0
118 lot,ier,lonuti,concepts=self.codex.poursu(self,1)
119 # Par la suite pour ne pas executer la commande pendant la phase
120 # d'execution on le remet à None
121 self.definition.op=None
122 # On demande la numerotation de la commande POURSUITE avec l'incrément
123 # lonuti pour qu'elle soit numérotée à la suite des commandes existantes.
124 ####CD self.set_icmd(lonuti) Non : on repart à zéro
127 while pos+80 < len(concepts)+1:
128 nomres=concepts[pos:pos+8]
129 concep=concepts[pos+8:pos+24]
130 nomcmd=concepts[pos+24:pos+40]
131 statut=concepts[pos+40:pos+48]
132 print nomres,concep,nomcmd,statut
133 if nomres[0] not in (' ','.','&') and statut != '&DETRUIT':
134 exec nomres+'='+string.lower(concep)+'()' in self.parent.g_context,d
135 elif statut == '&DETRUIT' : self.jdc.nsd = self.jdc.nsd+1
137 # ces ASSD seront écrasées par le pick.1,
138 # on vérifiera la cohérence de type entre glob.1 et pick.1
139 for k,v in d.items():
140 self.parent.NommerSdprod(v,k)
143 # Il peut exister un contexte python sauvegardé sous forme pickled
144 # On récupère ces objets après la restauration des concepts pour que
145 # la récupération des objets pickled soit prioritaire.
146 # On vérifie que les concepts relus dans glob.1 sont bien tous
147 # presents sous le meme nom et du meme type dans pick.1
148 # Le contexte est ensuite updaté (surcharge) et donc enrichi des
149 # variables qui ne sont pas des concepts.
150 # On supprime du pickle_context les concepts valant None, ca peut
151 # etre le cas des concepts non executés, placés après FIN.
152 pickle_context=get_pickled_context()
153 self.jdc.restore_pickled_attrs(pickle_context)
154 if pickle_context==None :
155 UTMESS('F','Poursuite',"Erreur a la relecture du fichier pick.1 : aucun objet sauvegardé ne sera récupéré")
157 from Cata.cata import ASSD,entier
158 from Noyau.N_CO import CO
159 for elem in pickle_context.keys():
160 if isinstance(pickle_context[elem], ASSD):
161 pickle_class=pickle_context[elem].__class__
162 # on rattache chaque assd au nouveau jdc courant (en poursuite)
163 pickle_context[elem].jdc=self.jdc
164 pickle_context[elem].parent=self.jdc
165 # rétablir le parent pour les attributs de la SD
166 pickle_context[elem].reparent_sd()
167 if elem in self.g_context.keys():
168 poursu_class=self.g_context[elem].__class__
169 if poursu_class!=pickle_class :
170 UTMESS('F','Poursuite',"Types incompatibles entre glob.1 et pick.1 pour concept de nom "+elem)
172 elif isinstance(pickle_context[elem],ASSD) and pickle_class not in (CO,entier) :
173 # on n'a pas trouvé le concept dans la base et sa classe est ASSD : ce n'est pas normal
174 # sauf dans le cas de CO : il n'a alors pas été typé et c'est normal qu'il soit absent de la base
175 # meme situation pour le type 'entier' produit uniquement par DEFI_FICHIER
176 UTMESS('F','Poursuite',"Concept de nom "+elem+" et de type "+str(pickle_class)+" introuvable dans la base globale")
178 if pickle_context[elem]==None : del pickle_context[elem]
179 self.g_context.update(pickle_context)
183 # Si le module d'execution n est pas accessible ou glob.1 absent on
184 # demande un fichier (EFICAS)
185 # Il faut éviter de réinterpréter le fichier à chaque appel de
187 if hasattr(self,'fichier_init'):
189 self.make_poursuite()
191 def get_pickled_context():
193 Cette fonction permet de réimporter dans le contexte courant du jdc (jdc.g_context)
194 les objets python qui auraient été sauvegardés, sous forme pickled, lors d'une
195 précédente étude. Un fichier pick.1 doit etre présent dans le répertoire de travail
197 if os.path.isfile("pick.1"):
201 # Le fichier pick.1 est présent. On essaie de récupérer les objets python sauvegardés
205 # Le contexte sauvegardé a été picklé en une seule fois. Il est seulement
206 # possible de le récupérer en bloc. Si cette opération echoue, on ne récupère
208 context=pickle.load(file)
211 # En cas d'erreur on ignore le contenu du fichier
212 # traceback.print_exc()
217 def POURSUITE_context(self,d):
219 Fonction op_init de la macro POURSUITE
221 # self représente la macro POURSUITE ...
222 d.update(self.g_context)
223 # Une commande POURSUITE n'est possible qu'au niveau le plus haut
224 # On ajoute directement les concepts dans le contexte du jdc
225 # XXX est ce que les concepts ne sont pas ajoutés plusieurs fois ??
226 for v in self.g_context.values():
227 if isinstance(v,ASSD) : self.jdc.sds.append(v)
229 def build_poursuite(self,**args):
231 Fonction ops pour la macro POURSUITE
233 # Pour POURSUITE on ne modifie pas la valeur initialisee dans ops.POURSUITE
234 # Il n y a pas besoin d executer self.codex.poursu (c'est deja fait dans
235 # la fonction sdprod de la commande (ops.POURSUITE))
237 self.jdc.UserError=self.codex.error
240 def INCLUDE(self,UNITE,**args):
242 Fonction sd_prod pour la macro INCLUDE
244 if not UNITE : return
245 if hasattr(self,'unite'):return
248 if self.jdc and self.jdc.par_lot == 'NON':
249 # On est en mode commande par commande, on appelle la methode speciale
252 self.make_include(unite=UNITE)
254 def INCLUDE_context(self,d):
256 Fonction op_init pour macro INCLUDE
258 for k,v in self.g_context.items():
261 def build_include(self,**args):
263 Fonction ops de la macro INCLUDE appelée lors de la phase de Build
265 # Pour presque toutes les commandes (sauf FORMULE et POURSUITE)
266 # le numero de la commande n est pas utile en phase de construction
267 # La macro INCLUDE ne sera pas numérotée (incrément=None)
271 # On n'execute pas l'ops d'include en phase BUILD car il ne sert a rien.
272 #ier=self.codex.opsexe(self,icmd,-1,1)
275 def detruire(self,d):
277 Cette fonction est la fonction op_init de la PROC DETRUIRE
279 if self["CONCEPT"]!=None:
281 for mc in self["CONCEPT"]:
283 if mcs is None:continue
284 if type(mcs) == types.ListType or type(mcs) == types.TupleType:
286 if isinstance(e,ASSD):
289 # traitement particulier pour les listes de concepts, on va mettre à None
290 # le terme de l'indice demandé dans la liste :
291 # nomconcept_i est supprimé, nomconcept[i]=None
292 indice=e[e.rfind('_')+1:]
293 concept_racine=e[:e.rfind('_')]
294 if indice!='' and d.has_key(concept_racine) and type(d[concept_racine])==types.ListType:
297 d[concept_racine][indici]=None
298 except ValueError : pass
299 # pour tous les concepts :
300 if d.has_key(e):del d[e]
301 if self.jdc.sds_dict.has_key(e):del self.jdc.sds_dict[e]
303 if isinstance(mcs,ASSD):
306 # traitement particulier pour les listes de concepts, on va mettre à None
307 # le terme de l'indice demandé dans la liste :
308 # nomconcept_i est supprimé, nomconcept[i]=None
309 indice=mcs[mcs.rfind('_')+1:]
310 concept_racine=mcs[:mcs.rfind('_')]
311 if indice!='' and d.has_key(concept_racine) and type(d[concept_racine])==types.ListType:
314 d[concept_racine][indici]=None
315 except ValueError : pass
316 # pour tous les concepts :
317 if d.has_key(mcs):del d[mcs]
318 if self.jdc.sds_dict.has_key(mcs):del self.jdc.sds_dict[mcs]
320 # On signale au parent que le concept s n'existe plus apres l'étape self
321 self.parent.delete_concept_after_etape(self,s)
323 def subst_materiau(text,NOM_MATER,EXTRACTION,UNITE_LONGUEUR):
325 Cette fonction retourne un texte obtenu à partir du texte passé en argument (text)
326 en substituant le nom du materiau par NOM_MATER
327 et en réalisant les extractions spéciifées dans EXTRACTION
329 lines=string.split(text,'\n')
331 ##### traitement de UNIT : facteur multiplicatif puissance de 10
332 regmcsu=re.compile(r" *(.*) *= *([^ ,]*) *## +([^ ]*) *([^ ]*)")
337 if m.group(3) == "UNIT":
338 if UNITE_LONGUEUR=='M' : coef = '0'
339 elif UNITE_LONGUEUR=='MM' : coef = m.group(4)
340 ll_u.append(m.group(1)+" = "+m.group(2)+coef)
341 else : ll_u.append(l)
342 else : ll_u.append(l)
344 ##### traitement de EXTRACTION
346 regmcf=re.compile(r" *(.*) *= *_F\( *## +(.*) +(.*)")
347 regmcs=re.compile(r" *(.*) *= *([^ ,]*) *, *## +([^ ]*) *([^ ]*)")
348 regfin=re.compile(r" *\) *")
354 temps[mcf]=e['TEMP_EVAL']
358 if m: # On a trouve un mot cle facteur "commentarise"
359 if m.group(2) == "SUBST": # il est de plus substituable
360 if temps.has_key(m.group(3)): # Il est a substituer
361 ll.append(" "+m.group(3)+"=_F(")
364 FLAG=1 # Indique que l'on est en cours de substitution
365 else: # Il n est pas a substituer car il n est pas dans la liste demandee
367 else: # Mot cle facteur commentarise non substituable
369 else: # La ligne ne contient pas un mot cle facteur commentarise
370 if FLAG == 0: # On n est pas en cours de substitution
372 else: # On est en cours de substitution. On cherche les mots cles simples commentarises
374 if m: # On a trouve un mot cle simple commentarise
375 if m.group(3) == "EVAL":
376 ll.append(" "+m.group(1)+' = '+m.group(4)+"("+str(TEMP)+'),')
377 elif m.group(3) == "SUPPR":
381 else: # On cherche la fin du mot cle facteur en cours de substitution
383 if m: # On l a trouve. On le supprime de la liste
393 l=re.sub(" *MAT *= *",NOM_MATER+" = ",l,1)
395 text=string.join(ll,'\n')
398 def post_INCLUDE(self):
400 Cette fonction est executée apres toutes les commandes d'un INCLUDE (RETOUR)
401 Elle sert principalement pour les INCLUDE_MATERIAU : remise a blanc du prefixe Fortran
403 self.codex.opsexe(self,0,-1,2)
405 def INCLUDE_MATERIAU(self,NOM_AFNOR,TYPE_MODELE,VARIANTE,TYPE_VALE,NOM_MATER,
406 EXTRACTION,UNITE_LONGUEUR,INFO,**args):
408 Fonction sd_prod pour la macro INCLUDE_MATERIAU
410 mat=string.join((NOM_AFNOR,'_',TYPE_MODELE,'_',VARIANTE,'.',TYPE_VALE),'')
411 if not hasattr(self,'mat') or self.mat != mat or self.nom_mater != NOM_MATER :
412 # On récupère le répertoire des matériaux dans les arguments
413 # supplémentaires du JDC
414 rep_mat=self.jdc.args.get("rep_mat","NOrep_mat")
415 f=os.path.join(rep_mat,mat)
417 self.nom_mater=NOM_MATER
418 if not os.path.isfile(f):
420 self.make_contexte(f,"#Texte sans effet pour reinitialiser le contexte a vide\n")
421 raise "Erreur sur le fichier materiau: "+f
422 # Les materiaux sont uniquement disponibles en syntaxe Python
423 # On lit le fichier et on supprime les éventuels \r
424 text=string.replace(open(f).read(),'\r\n','\n')
425 # On effectue les substitutions necessaires
426 self.text= subst_materiau(text,NOM_MATER,EXTRACTION,UNITE_LONGUEUR)
428 print "INCLUDE_MATERIAU: ", self.mat,' ',NOM_MATER,'\n'
430 # on execute le texte fourni dans le contexte forme par
431 # le contexte de l etape pere (global au sens Python)
432 # et le contexte de l etape (local au sens Python)
433 # Il faut auparavant l'enregistrer aupres du module linecache (utile pour nommage.py)
434 linecache.cache[f]=0,0,string.split(self.text,'\n'),f
436 self.postexec=post_INCLUDE
438 if self.jdc.par_lot == 'NON':
439 # On est en mode commande par commande, on appelle la methode speciale
442 self.make_contexte(f,self.text)
443 for k,v in self.g_context.items() :
444 if isinstance(v,ASSD) and k!=v.nom : del self.g_context[k]
446 def build_procedure(self,**args):
448 Fonction ops de la macro PROCEDURE appelée lors de la phase de Build
451 # Pour presque toutes les commandes (sauf FORMULE et POURSUITE)
452 # le numero de la commande n est pas utile en phase de construction
453 # On ne numérote pas une macro PROCEDURE (incrément=None)
456 #ier=self.codex.opsexe(self,icmd,-1,3)
459 def build_DEFI_FICHIER(self,**args):
461 Fonction ops de la macro DEFI_FICHIER
466 ier=self.codex.opsexe(self,icmd,-1,26)