1 #@ MODIF ops Cata DATE 23/03/2010 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
30 from Accas import ASSD
31 from Noyau.ascheckers import CheckLog
36 # Si le module aster est présent, on le connecte
39 Build.B_CODE.CODE.codex=aster
41 from Utilitai.Utmess import UTMESS
42 from Build.B_SENSIBILITE_MEMO_NOM_SENSI import MEMORISATION_SENSIBILITE
43 from Execution.E_Global import MessageLog
48 def commun_DEBUT_POURSUITE(jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM):
49 """Fonction sdprod partie commune à DEBUT et POURSUITE.
50 (on stocke un entier au lieu du logique)
53 jdc.impr_macro = int(IMPR_MACRO == 'OUI')
54 jdc.jxveri = int(CODE != None or (DEBUG != None and DEBUG['JXVERI'] == 'OUI'))
55 jdc.sdveri = int(DEBUG != None and DEBUG['SDVERI'] == 'OUI')
57 jdc.sd_checker = CheckLog()
59 jdc.fico = CODE['NOM']
61 # en POURSUITE, ne pas écraser la mémorisation existante.
62 if not hasattr(jdc, 'memo_sensi'):
63 jdc.memo_sensi = MEMORISATION_SENSIBILITE()
64 jdc.memo_sensi.reparent(jdc)
66 # ne faire qu'une fois
67 if not hasattr(jdc, 'msg_init'):
68 # messages d'alarmes désactivés
70 if not type(IGNORE_ALARM) in (list, tuple):
71 IGNORE_ALARM = [IGNORE_ALARM]
72 for idmess in IGNORE_ALARM:
73 MessageLog.disable_alarm(idmess)
75 # en POURSUITE, conserver le catalogue de comportement picklé
76 if not hasattr(jdc, 'catalc'):
77 from Comportement import catalc
83 def DEBUT(self, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, **args):
85 Fonction sdprod de la macro DEBUT
87 # La commande DEBUT ne peut exister qu'au niveau jdc
88 if self.jdc is not self.parent :
89 raise Accas.AsException("La commande DEBUT ne peut exister qu'au niveau jdc")
91 commun_DEBUT_POURSUITE(self.jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM)
94 def build_debut(self,**args):
96 Fonction ops pour la macro DEBUT
98 self.jdc.UserError=self.codex.error
100 if self.jdc.par_lot == 'NON' :
102 # On execute la fonction debut pour initialiser les bases
103 # Cette execution est indispensable avant toute autre action sur ASTER
104 # op doit etre un entier car la fonction debut appelle GCECDU qui demande
105 # le numero de l'operateur associé (getoper)
108 lot,ier=self.codex.debut(self,1)
109 # On remet op a None juste apres pour eviter que la commande DEBUT
110 # ne soit executée dans la phase d'execution
111 self.definition.op=None
114 def POURSUITE(self, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, **args):
116 Fonction sdprod de la macro POURSUITE
118 # La commande POURSUITE ne peut exister qu'au niveau jdc
119 if self.jdc is not self.parent :
120 raise Accas.AsException("La commande POURSUITE ne peut exister qu'au niveau jdc")
122 commun_DEBUT_POURSUITE(self.jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM)
124 if (self.codex and os.path.isfile("glob.1") or os.path.isfile("bhdf.1")):
125 # Le module d'execution est accessible et glob.1 est present
126 # Pour eviter de rappeler plusieurs fois la sequence d'initialisation
127 # on memorise avec l'attribut fichier_init que l'initialisation
129 if hasattr(self,'fichier_init'):return
130 self.fichier_init='glob.1'
132 # le sous programme fortran appelé par self.codex.poursu demande le numero
133 # de l'operateur (GCECDU->getoper), on lui donne la valeur 0
135 lot,ier,lonuti,concepts=self.codex.poursu(self,1)
136 # Par la suite pour ne pas executer la commande pendant la phase
137 # d'execution on le remet à None
138 self.definition.op=None
139 # On demande la numerotation de la commande POURSUITE avec l'incrément
140 # lonuti pour qu'elle soit numérotée à la suite des commandes existantes.
141 ####CD self.set_icmd(lonuti) Non : on repart à zéro
144 while pos+80 < len(concepts)+1:
145 nomres=concepts[pos:pos+8]
146 concep=concepts[pos+8:pos+24]
147 nomcmd=concepts[pos+24:pos+40]
148 statut=concepts[pos+40:pos+48]
149 print nomres,concep,nomcmd,statut
150 if nomres[0] not in (' ','.','&') and statut != '&DETRUIT':
151 exec nomres+'='+string.lower(concep)+'()' in self.parent.g_context,d
152 elif statut == '&DETRUIT' : self.jdc.nsd = self.jdc.nsd+1
154 # ces ASSD seront écrasées par le pick.1,
155 # on vérifiera la cohérence de type entre glob.1 et pick.1
156 for k,v in d.items():
157 self.parent.NommerSdprod(v,k)
160 # Il peut exister un contexte python sauvegardé sous forme pickled
161 # On récupère ces objets après la restauration des concepts pour que
162 # la récupération des objets pickled soit prioritaire.
163 # On vérifie que les concepts relus dans glob.1 sont bien tous
164 # presents sous le meme nom et du meme type dans pick.1
165 # Le contexte est ensuite updaté (surcharge) et donc enrichi des
166 # variables qui ne sont pas des concepts.
167 # On supprime du pickle_context les concepts valant None, ca peut
168 # etre le cas des concepts non executés, placés après FIN.
169 pickle_context=get_pickled_context()
170 if pickle_context==None :
171 UTMESS('F','SUPERVIS_86')
173 self.jdc.restore_pickled_attrs(pickle_context)
174 from Cata.cata import ASSD,entier
175 from Noyau.N_CO import CO
176 for elem in pickle_context.keys():
177 if isinstance(pickle_context[elem], ASSD):
178 pickle_class=pickle_context[elem].__class__
179 # on rattache chaque assd au nouveau jdc courant (en poursuite)
180 pickle_context[elem].jdc=self.jdc
181 pickle_context[elem].parent=self.jdc
182 # le marquer comme 'executed'
183 pickle_context[elem].executed = 1
184 # pour que sds_dict soit cohérent avec g_context
185 self.jdc.sds_dict[elem] = pickle_context[elem]
186 if elem != pickle_context[elem].nom:
187 name = re.sub('_([0-9]+)$', '[\\1]', pickle_context[elem].nom)
188 UTMESS('A', 'SUPERVIS_93', valk=(elem, name))
189 del pickle_context[elem]
191 # rétablir le parent pour les attributs de la SD
192 pickle_context[elem].reparent_sd()
193 if elem in self.g_context.keys():
194 poursu_class=self.g_context[elem].__class__
195 if poursu_class!=pickle_class :
196 UTMESS('F','SUPERVIS_87',valk=[elem])
198 elif isinstance(pickle_context[elem],ASSD) and pickle_class not in (CO,entier) :
199 # on n'a pas trouvé le concept dans la base et sa classe est ASSD : ce n'est pas normal
200 # sauf dans le cas de CO : il n'a alors pas été typé et c'est normal qu'il soit absent de la base
201 # meme situation pour le type 'entier' produit uniquement par DEFI_FICHIER
202 UTMESS('F','SUPERVIS_88',valk=[elem,str(pickle_class)])
204 if pickle_context[elem]==None : del pickle_context[elem]
205 self.g_context.update(pickle_context)
209 # Si le module d'execution n est pas accessible ou glob.1 absent on
210 # demande un fichier (EFICAS)
211 # Il faut éviter de réinterpréter le fichier à chaque appel de
213 if hasattr(self,'fichier_init'):
215 self.make_poursuite()
217 def get_pickled_context():
219 Cette fonction permet de réimporter dans le contexte courant du jdc (jdc.g_context)
220 les objets python qui auraient été sauvegardés, sous forme pickled, lors d'une
221 précédente étude. Un fichier pick.1 doit etre présent dans le répertoire de travail
224 if not os.path.isfile(fpick):
227 # Le fichier pick.1 est présent. On essaie de récupérer les objets python sauvegardés
231 # Le contexte sauvegardé a été picklé en une seule fois. Il est seulement
232 # possible de le récupérer en bloc. Si cette opération echoue, on ne récupère
234 context=pickle.load(file)
237 # En cas d'erreur on ignore le contenu du fichier
238 traceback.print_exc()
243 def POURSUITE_context(self,d):
245 Fonction op_init de la macro POURSUITE
247 # self représente la macro POURSUITE ...
248 d.update(self.g_context)
249 # Une commande POURSUITE n'est possible qu'au niveau le plus haut
250 # On ajoute directement les concepts dans le contexte du jdc
251 # XXX est ce que les concepts ne sont pas ajoutés plusieurs fois ??
252 for v in self.g_context.values():
253 if isinstance(v,ASSD) :
254 self.jdc.sds.append(v)
256 def build_poursuite(self,**args):
258 Fonction ops pour la macro POURSUITE
260 # Pour POURSUITE on ne modifie pas la valeur initialisee dans ops.POURSUITE
261 # Il n y a pas besoin d executer self.codex.poursu (c'est deja fait dans
262 # la fonction sdprod de la commande (ops.POURSUITE))
264 self.jdc.UserError=self.codex.error
267 def INCLUDE(self,UNITE,**args):
269 Fonction sd_prod pour la macro INCLUDE
271 if not UNITE : return
272 if hasattr(self,'unite'):return
275 if self.jdc and self.jdc.par_lot == 'NON':
276 # On est en mode commande par commande, on appelle la methode speciale
279 self.make_include(unite=UNITE)
281 def INCLUDE_context(self,d):
283 Fonction op_init pour macro INCLUDE
285 for k,v in self.g_context.items():
288 def build_include(self,**args):
290 Fonction ops de la macro INCLUDE appelée lors de la phase de Build
292 # Pour presque toutes les commandes (sauf FORMULE et POURSUITE)
293 # le numero de la commande n est pas utile en phase de construction
294 # La macro INCLUDE ne sera pas numérotée (incrément=None)
298 # On n'execute pas l'ops d'include en phase BUILD car il ne sert a rien.
299 #ier=self.codex.opsexe(self,icmd,-1,1)
302 def detruire(self,d):
304 Cette fonction est la fonction op_init de la PROC DETRUIRE
308 # par nom de concept (typ=assd)
309 if self["CONCEPT"] != None:
310 for mc in self["CONCEPT"]:
312 if type(mcs) not in (list, tuple):
315 # par chaine de caractères (typ='TXM')
316 if self["OBJET"] != None:
317 for mc in self["OBJET"]:
319 if type(mcs) not in (list, tuple):
321 # longueur <= 8, on cherche les concepts existants
323 assert type(nom) in (str, unicode), 'On attend une chaine de caractères : %s' % nom
324 if len(nom.strip()) <= 8:
325 if self.jdc.sds_dict.get(nom) != None:
326 list_co.add(self.jdc.sds_dict[nom])
327 elif d.get(nom) != None:
329 #else uniquement destruction des objets jeveux
332 assert isinstance(co, ASSD), 'On attend un concept : %s (type=%s)' % (co, type(co))
334 # traitement particulier pour les listes de concepts, on va mettre à None
335 # le terme de l'indice demandé dans la liste :
336 # nomconcept_i est supprimé, nomconcept[i]=None
338 if i > 0 and not nom.endswith('_'):
339 concept_racine = nom[:i]
340 if d.has_key(concept_racine) and type(d[concept_racine]) is list:
343 d[concept_racine][num] = None
344 except (ValueError, IndexError):
345 # cas : RESU_aaa ou (RESU_8 avec RESU[8] non initialisé)
347 # pour tous les concepts :
350 if self.jdc.sds_dict.has_key(nom):
351 del self.jdc.sds_dict[nom]
352 # On signale au parent que le concept s n'existe plus apres l'étape self
353 self.parent.delete_concept_after_etape(self, co)
354 # marque comme détruit == non executé
358 def subst_materiau(text,NOM_MATER,EXTRACTION,UNITE_LONGUEUR):
360 Cette fonction retourne un texte obtenu à partir du texte passé en argument (text)
361 en substituant le nom du materiau par NOM_MATER
362 et en réalisant les extractions spéciifées dans EXTRACTION
364 lines=string.split(text,'\n')
366 ##### traitement de UNIT : facteur multiplicatif puissance de 10
367 regmcsu=re.compile(r" *(.*) *= *([^ ,]*) *## +([^ ]*) *([^ ]*)")
372 if m.group(3) == "UNIT":
373 if UNITE_LONGUEUR=='M' : coef = '0'
374 elif UNITE_LONGUEUR=='MM' : coef = m.group(4)
375 ll_u.append(m.group(1)+" = "+m.group(2)+coef)
376 else : ll_u.append(l)
377 else : ll_u.append(l)
379 ##### traitement de EXTRACTION
381 regmcf=re.compile(r" *(.*) *= *_F\( *## +(.*) +(.*)")
382 regmcs=re.compile(r" *(.*) *= *([^ ,]*) *, *## +([^ ]*) *([^ ]*)")
383 regfin=re.compile(r" *\) *")
389 temps[mcf]=e['TEMP_EVAL']
393 if m: # On a trouve un mot cle facteur "commentarise"
394 if m.group(2) == "SUBST": # il est de plus substituable
395 if temps.has_key(m.group(3)): # Il est a substituer
396 ll.append(" "+m.group(3)+"=_F(")
399 FLAG=1 # Indique que l'on est en cours de substitution
400 else: # Il n est pas a substituer car il n est pas dans la liste demandee
402 else: # Mot cle facteur commentarise non substituable
404 else: # La ligne ne contient pas un mot cle facteur commentarise
405 if FLAG == 0: # On n est pas en cours de substitution
407 else: # On est en cours de substitution. On cherche les mots cles simples commentarises
409 if m: # On a trouve un mot cle simple commentarise
410 if m.group(3) == "EVAL":
411 ll.append(" "+m.group(1)+' = '+m.group(4)+"("+str(TEMP)+'),')
412 elif m.group(3) == "SUPPR":
416 else: # On cherche la fin du mot cle facteur en cours de substitution
418 if m: # On l a trouve. On le supprime de la liste
428 l=re.sub(" *MAT *= *",NOM_MATER+" = ",l,1)
430 text=string.join(ll,'\n')
433 def post_INCLUDE(self):
435 Cette fonction est executée apres toutes les commandes d'un INCLUDE (RETOUR)
436 Elle sert principalement pour les INCLUDE_MATERIAU : remise a blanc du prefixe Fortran
438 self.codex.opsexe(self,0,-1,2)
440 def INCLUDE_MATERIAU(self,NOM_AFNOR,TYPE_MODELE,VARIANTE,TYPE_VALE,NOM_MATER,
441 EXTRACTION,UNITE_LONGUEUR,INFO,**args):
443 Fonction sd_prod pour la macro INCLUDE_MATERIAU
445 mat=string.join((NOM_AFNOR,'_',TYPE_MODELE,'_',VARIANTE,'.',TYPE_VALE),'')
446 if not hasattr(self,'mat') or self.mat != mat or self.nom_mater != NOM_MATER :
447 # On récupère le répertoire des matériaux dans les arguments
448 # supplémentaires du JDC
449 rep_mat=self.jdc.args.get("rep_mat","NOrep_mat")
450 f=os.path.join(rep_mat,mat)
452 self.nom_mater=NOM_MATER
453 if not os.path.isfile(f):
455 self.make_contexte(f,"#Texte sans effet pour reinitialiser le contexte a vide\n")
456 raise "Erreur sur le fichier materiau: "+f
457 # Les materiaux sont uniquement disponibles en syntaxe Python
458 # On lit le fichier et on supprime les éventuels \r
459 text=string.replace(open(f).read(),'\r\n','\n')
460 # On effectue les substitutions necessaires
461 self.text= subst_materiau(text,NOM_MATER,EXTRACTION,UNITE_LONGUEUR)
463 print "INCLUDE_MATERIAU: ", self.mat,' ',NOM_MATER,'\n'
465 # on execute le texte fourni dans le contexte forme par
466 # le contexte de l etape pere (global au sens Python)
467 # et le contexte de l etape (local au sens Python)
468 # Il faut auparavant l'enregistrer aupres du module linecache (utile pour nommage.py)
469 linecache.cache[f]=0,0,string.split(self.text,'\n'),f
471 self.postexec=post_INCLUDE
473 if self.jdc.par_lot == 'NON':
474 # On est en mode commande par commande, on appelle la methode speciale
477 self.make_contexte(f,self.text)
478 for k,v in self.g_context.items() :
479 if isinstance(v,ASSD) and k!=v.nom : del self.g_context[k]
481 def build_procedure(self,**args):
483 Fonction ops de la macro PROCEDURE appelée lors de la phase de Build
486 # Pour presque toutes les commandes (sauf FORMULE et POURSUITE)
487 # le numero de la commande n est pas utile en phase de construction
488 # On ne numérote pas une macro PROCEDURE (incrément=None)
491 #ier=self.codex.opsexe(self,icmd,-1,3)
494 def build_DEFI_FICHIER(self,**args):
496 Fonction ops de la macro DEFI_FICHIER
501 ier=self.codex.opsexe(self,icmd,-1,26)