]> SALOME platform Git repositories - tools/eficas.git/blob - generator/generator_python.py
Salome HOME
PN : pour edition en colonnes dans le fichier produit
[tools/eficas.git] / generator / generator_python.py
1 # -*- coding: utf-8 -*-
2 #            CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
18 #
19 #
20 # ======================================================================
21 """
22     Ce module contient le plugin generateur de fichier au format 
23     python pour EFICAS.
24
25 """
26 import traceback
27 import types,string,re
28
29 from Noyau import N_CR
30 from Noyau.N_utils import repr_float
31 import Accas
32 import Extensions
33 from Extensions.parametre import ITEM_PARAMETRE
34 from Formatage import Formatage
35
36 def entryPoint():
37    """
38        Retourne les informations nécessaires pour le chargeur de plugins
39
40        Ces informations sont retournées dans un dictionnaire
41    """
42    return {
43         # Le nom du plugin
44           'name' : 'python',
45         # La factory pour créer une instance du plugin
46           'factory' : PythonGenerator,
47           }
48
49
50 class PythonGenerator:
51    """
52        Ce generateur parcourt un objet de type JDC et produit
53        un fichier au format python 
54
55        L'acquisition et le parcours sont réalisés par la méthode
56        generator.gener(objet_jdc,format)
57
58        L'écriture du fichier au format ini par appel de la méthode
59        generator.writefile(nom_fichier)
60
61        Ses caractéristiques principales sont exposées dans des attributs 
62        de classe :
63          - extensions : qui donne une liste d'extensions de fichier préconisées
64
65    """
66    # Les extensions de fichier préconisées
67    extensions=('.comm',)
68
69    def __init__(self,cr=None):
70       # Si l'objet compte-rendu n'est pas fourni, on utilise le compte-rendu standard
71       if cr :
72          self.cr=cr
73       else:
74          self.cr=N_CR.CR(debut='CR generateur format python pour python',
75                          fin='fin CR format python pour python')
76       # Le texte au format python est stocké dans l'attribut text
77       self.text=''
78       self.appli=None
79
80    def writefile(self,filename):
81       fp=open(filename,'w')
82       fp.write(self.text)
83       fp.close()
84
85    def gener(self,obj,format='brut'):
86       """
87           Retourne une représentation du JDC obj sous une
88           forme qui est paramétrée par format.
89           Si format vaut 'brut', retourne une liste de listes de ...
90           Si format vaut 'standard', retourne un texte obtenu par concaténation de la liste
91           Si format vaut 'beautifie', retourne le meme texte beautifié
92       """
93       self.appli=obj.get_jdc_root().appli
94       #self.appli=obj.appli
95       liste= self.generator(obj)
96       if format == 'brut':
97          self.text=liste
98       elif format == 'standard':
99          self.text=string.join(liste)
100       elif format == 'beautifie':
101          jdc_formate = Formatage(liste,mode='.py')
102          self.text=jdc_formate.formate_jdc()
103       else:
104          raise "Format pas implémenté : "+format
105       return self.text
106
107    def generator(self,obj):
108       """
109          Cette methode joue un role d'aiguillage en fonction du type de obj
110          On pourrait utiliser les méthodes accept et visitxxx à la 
111          place (dépend des gouts !!!)
112       """
113       # ATTENTION a l'ordre des tests : il peut avoir de l'importance (héritage)
114       if isinstance(obj,Accas.PROC_ETAPE):
115          return self.generPROC_ETAPE(obj)
116       # Attention doit etre placé avant MACRO (raison : héritage)
117       elif isinstance(obj,Accas.FORM_ETAPE):
118          return self.generFORM_ETAPE(obj)
119       elif isinstance(obj,Accas.MACRO_ETAPE):
120          return self.generMACRO_ETAPE(obj)
121       elif isinstance(obj,Accas.ETAPE):
122          return self.generETAPE(obj)
123       elif isinstance(obj,Accas.MCFACT):
124          return self.generMCFACT(obj)
125       elif isinstance(obj,Accas.MCList):
126          return self.generMCList(obj)
127       elif isinstance(obj,Accas.MCBLOC):
128          return self.generMCBLOC(obj)
129       elif isinstance(obj,Accas.MCSIMP):
130          return self.generMCSIMP(obj)
131       elif isinstance(obj,Accas.ASSD):
132          return self.generASSD(obj)
133       elif isinstance(obj,Accas.ETAPE_NIVEAU):
134          return self.generETAPE_NIVEAU(obj)
135       elif isinstance(obj,Accas.COMMENTAIRE):
136          return self.generCOMMENTAIRE(obj)
137       # Attention doit etre placé avant PARAMETRE (raison : héritage)
138       elif isinstance(obj,Accas.PARAMETRE_EVAL):
139          return self.generPARAMETRE_EVAL(obj)
140       elif isinstance(obj,Accas.PARAMETRE):
141          return self.generPARAMETRE(obj)
142       elif isinstance(obj,Accas.EVAL):
143          return self.generEVAL(obj)
144       elif isinstance(obj,Accas.COMMANDE_COMM):
145          return self.generCOMMANDE_COMM(obj)
146       elif isinstance(obj,Accas.JDC):
147          return self.generJDC(obj)
148       elif isinstance(obj,Accas.MCNUPLET):
149          return self.generMCNUPLET(obj)
150       elif isinstance(obj,ITEM_PARAMETRE):
151          return self.generITEM_PARAMETRE(obj)
152       else:
153          raise "Type d'objet non prévu",obj
154
155    def generJDC(self,obj):
156       """
157          Cette méthode convertit un objet JDC en une liste de chaines de
158          caractères à la syntaxe python
159       """
160       l=[]
161       if obj.definition.l_niveaux == ():
162          # Il n'y a pas de niveaux
163          for etape in obj.etapes:
164             l.append(self.generator(etape))
165       else:
166          # Il y a des niveaux
167          for etape_niveau in obj.etapes_niveaux:
168             l.extend(self.generator(etape_niveau))
169       if l != [] :
170          # Si au moins une étape, on ajoute le retour chariot sur la dernière étape
171          if type(l[-1])==types.ListType:
172             l[-1][-1] = l[-1][-1]+'\n'
173          elif type(l[-1])==types.StringType:
174             l[-1] = l[-1]+'\n'
175       return l
176
177    def generMCNUPLET(self,obj):
178       """ 
179           Méthode générant une représentation de self permettant son ecriture
180           dans le format python
181       """
182       l=[]
183       l.append('(')
184       for v in obj.mc_liste:
185         text = re.sub(".*=","",self.generator(v))
186         l.append(text)
187       l.append('),')
188       return l
189
190    def generCOMMANDE_COMM(self,obj):
191       """
192          Cette méthode convertit un COMMANDE_COMM
193          en une liste de chaines de caractères à la syntaxe python
194       """
195       l_lignes = string.split(obj.valeur,'\n')
196       txt=''
197       for ligne in l_lignes:
198           txt = txt + '##'+ligne+'\n'
199       return txt
200
201    def generEVAL(self,obj):
202       """
203          Cette méthode convertit un EVAL
204          en une liste de chaines de caractères à la syntaxe python
205       """
206       return 'EVAL("""'+ obj.valeur +'""")'
207
208    def generCOMMENTAIRE(self,obj):
209       """
210          Cette méthode convertit un COMMENTAIRE
211          en une liste de chaines de caractères à la syntaxe python
212       """
213       # modification pour répondre à la demande de C. Durand, d'éviter
214       # l'ajout systématique d'un dièse, à la suite du commentaire
215       # Dans la chaine de caracteres obj.valeur, on supprime le dernier
216       # saut de ligne
217       sans_saut = re.sub("\n$","",obj.valeur)
218       l_lignes = string.split(sans_saut,'\n')
219       txt=''
220       for ligne in l_lignes:
221         txt = txt + '#'+ligne+'\n'
222
223       # suppression du dernier saut de ligne
224       txt = re.sub("\n$","",txt)
225       return txt
226
227    def generPARAMETRE_EVAL(self,obj):
228       """
229          Cette méthode convertit un PARAMETRE_EVAL
230          en une liste de chaines de caractères à la syntaxe python
231       """
232       if obj.valeur == None:
233          return obj.nom + ' = None ;\n'
234       else:
235          return obj.nom + ' = '+ self.generator(obj.valeur) +';\n'
236
237    def generITEM_PARAMETRE(self,obj):
238        return repr(obj) 
239
240    def generPARAMETRE(self,obj):
241       """
242          Cette méthode convertit un PARAMETRE
243          en une liste de chaines de caractères à la syntaxe python
244       """
245       if type(obj.valeur) == types.StringType:
246         # PN pour corriger le bug a='3+4' au lieu de a= 3+4
247         #return obj.nom + " = '" + obj.valeur + "';\n"
248         return obj.nom + " = " + obj.valeur + ";\n"
249       else:
250         return obj.nom + ' = ' + str(obj.valeur) + ';\n'
251
252    def generETAPE_NIVEAU(self,obj):
253       """
254          Cette méthode convertit une étape niveau
255          en une liste de chaines de caractères à la syntaxe python
256       """
257       l=[]
258       if obj.etapes_niveaux == []:
259         for etape in obj.etapes:
260           l.append(self.generator(etape))
261       else:
262         for etape_niveau in obj.etapes_niveaux:
263           l.extend(self.generator(etape_niveau))
264       return l
265
266    def generETAPE(self,obj):
267       """
268          Cette méthode convertit une étape
269          en une liste de chaines de caractères à la syntaxe python
270       """
271       try:
272         sdname= self.generator(obj.sd)
273       except:
274         sdname='sansnom'
275       l=[]
276       label=sdname + '='+obj.definition.nom+'('
277       l.append(label)
278       if obj.reuse != None :
279         str = 'reuse ='+ self.generator(obj.reuse) + ','
280         l.append(str)
281       for v in obj.mc_liste:
282         if isinstance(v,Accas.MCBLOC) :
283           liste=self.generator(v)
284           for mocle in liste :
285             l.append(mocle)
286         elif isinstance(v,Accas.MCSIMP) :
287           text=self.generator(v)
288           l.append(v.nom+'='+text)
289         else:
290           # MCFACT ou MCList
291           liste=self.generator(v)
292           liste[0]=v.nom+'='+liste[0]
293           l.append(liste)
294       if len(l) == 1:
295         l[0]=label+');'
296       else :
297         l.append(');')
298       return l
299
300    def generFORM_ETAPE(self,obj):
301         """
302             Méthode particulière pour les objets de type FORMULE
303         """
304         l=[]
305         nom = obj.get_nom()
306         if nom == '' : nom = 'sansnom'
307         l.append(nom + ' = FORMULE(')
308         for v in obj.mc_liste:
309             text=self.generator(v)
310             l.append(v.nom+'='+text)
311         l.append(');')
312         return l
313
314    def generMACRO_ETAPE(self,obj):
315       """
316          Cette méthode convertit une macro-étape
317          en une liste de chaines de caractères à la syntaxe python
318       """
319       try:
320         if obj.sd == None:
321           sdname=''
322         else:
323           sdname= self.generator(obj.sd)+'='
324       except:
325         sdname='sansnom='
326       l=[]
327       label = sdname + obj.definition.nom+'('
328       l.append(label)
329       if obj.reuse != None:
330          # XXX faut il la virgule ou pas ????
331          str = "reuse =" + self.generator(obj.reuse) + ','
332          l.append(str)
333       for v in obj.mc_liste:
334         if isinstance(v,Accas.MCBLOC) :
335           liste=self.generator(v)
336           for mocle in liste :
337             l.append(mocle)
338         elif isinstance(v,Accas.MCSIMP) :
339           text=self.generator(v)
340           l.append(v.nom+'='+text)
341         else:
342           # MCFACT ou MCList
343           liste=self.generator(v)
344           liste[0]=v.nom+'='+liste[0]
345           l.append(liste)
346
347       if len(l) == 1:
348         l[0]=label+');'
349       else :
350         l.append(');')
351       return l
352
353    def generPROC_ETAPE(self,obj):
354       """
355          Cette méthode convertit une PROC étape
356          en une liste de chaines de caractères à la syntaxe python
357       """
358       l=[]
359       label=obj.definition.nom+'('
360       l.append(label)
361       for v in obj.mc_liste:
362         if isinstance(v,Accas.MCBLOC) :
363           liste=self.generator(v)
364           for mocle in liste :
365             l.append(mocle)
366         elif isinstance(v,Accas.MCSIMP) :
367           text=self.generator(v)
368           l.append(v.nom+'='+text)
369         else:
370           # MCFACT ou MCList
371           liste=self.generator(v)
372           liste[0]=v.nom+'='+liste[0]
373           l.append(liste)
374
375       if len(l) == 1:
376         l[0]=label+');'
377       else :
378         l.append(');')
379       return l
380
381    def generASSD(self,obj):
382       """
383           Convertit un objet dérivé d'ASSD en une chaine de caractères à la
384           syntaxe python
385       """
386       return obj.get_name()
387
388    def generMCFACT(self,obj):
389       """
390           Convertit un objet MCFACT en une liste de chaines de caractères à la
391           syntaxe python
392       """
393       l=[]
394       l.append('_F(')
395       for v in obj.mc_liste:
396          if not isinstance(v,Accas.MCSIMP) and not isinstance (v,Accas.MCBLOC) :
397            # on est en présence d'une entite composée : on récupère une liste
398            liste=self.generator(v)
399            liste[0]=v.nom+'='+liste[0]
400            l.append(liste)
401          elif isinstance(v,Accas.MCBLOC):
402            liste=self.generator(v)
403            for arg in liste :
404              l.append(arg)
405          else:
406            # on est en présence d'un MCSIMP : on récupère une string
407            text =self.generator(v)
408            l.append(v.nom+'='+text)
409       # il faut être plus subtil dans l'ajout de la virgule en différenciant 
410       # le cas où elle est obligatoire (si self a des frères cadets 
411       # dans self.parent) ou non
412       # (cas où self est seul ou le benjamin de self.parent)
413       l.append('),')
414       return l
415
416    def generMCList(self,obj):
417       """
418           Convertit un objet MCList en une liste de chaines de caractères à la
419           syntaxe python
420       """
421       if len(obj.data) > 1:
422          l=['(']
423          for mcfact in obj.data: l.append(self.generator(mcfact))
424          l.append('),')
425       else:
426          l= self.generator(obj.data[0])
427       return l
428
429    def generMCBLOC(self,obj):
430       """
431           Convertit un objet MCBLOC en une liste de chaines de caractères à la
432           syntaxe python
433       """
434       l=[]
435       for v in obj.mc_liste:
436         if isinstance(v,Accas.MCBLOC) :
437           liste=self.generator(v)
438           for mocle in liste :
439             l.append(mocle)
440         elif isinstance(v,Accas.MCList):
441           liste=self.generator(v)
442           liste[0]=v.nom+'='+liste[0]
443           for mocle in liste :
444             l.append(mocle)
445         else:
446           data=self.generator(v)
447           if type(data) == types.ListType:
448             data[0]=v.nom+'='+data[0]
449           else:
450             data=v.nom+'='+data
451           l.append(data)
452       return l
453
454    def generMCSIMP(self,obj) :
455       """
456           Convertit un objet MCSIMP en une liste de chaines de caractères à la
457           syntaxe python
458       """
459       if type(obj.valeur) in (types.TupleType,types.ListType) :
460          s = ''
461          for val in obj.valeur :
462             if type(val) == types.InstanceType :
463                if hasattr(obj.etape,'sdprods') and val in obj.etape.sdprods :
464                   s = s + "CO('"+ self.generator(val) +"')"
465                elif val.__class__.__name__ == 'CO':
466                   s = s + "CO('"+ self.generator(val) +"')"
467                elif isinstance(val,Accas.PARAMETRE):
468                   # il ne faut pas prendre la string que retourne gener
469                   # mais seulement le nom dans le cas d'un paramètre
470                   s = s + val.nom
471                else:
472                   s = s + self.generator(val)
473             elif type(val) == types.FloatType :
474                # Pour un flottant on utilise str qui a une precision de
475                # "seulement" 12 chiffres : evite les flottants du genre 0.599999999999998
476                s2=str(val)
477                try :
478                  clefobj=obj.GetNomConcept()
479                  if self.appli.dict_reels.has_key(clefobj):
480                     if self.appli.dict_reels[clefobj].has_key(val):
481                        s2=self.appli.dict_reels[clefobj][val]
482                except:
483                   pass
484                s = s + s2
485             else :
486                # Pour les autres types on utilise repr
487                s = s + `val`
488             s = s + ','
489          if len(obj.valeur) > 1:
490             s = '(' + s + '),'
491          if obj.nbrColonnes() :
492             s=self.formatColonnes(obj.nbrColonnes(),s)
493       else :
494          val=obj.valeur
495          if type(val) == types.InstanceType :
496             if hasattr(obj.etape,'sdprods') and val in obj.etape.sdprods :
497                s = "CO('"+ self.generator(val) +"')"
498             elif val.__class__.__name__ == 'CO':
499                s = "CO('"+ self.generator(val) +"')"
500             elif isinstance(val,Accas.PARAMETRE):
501                # il ne faut pas prendre la string que retourne gener
502                # mais seulement le nom dans le cas d'un paramètre
503                s = val.nom
504             elif isinstance(val,Extensions.parametre.PARAMETRE):
505                s = val.nom
506             else:
507                s = self.generator(val)
508          elif type(val) == types.FloatType :
509             # Pour un flottant on utilise str 
510             # ou la notation scientifique
511             s = str(val)
512             try :
513               clefobj=obj.GetNomConcept()
514               if self.appli.dict_reels.has_key(clefobj):
515                  if self.appli.dict_reels[clefobj].has_key(val):
516                     s=self.appli.dict_reels[clefobj][val]
517             except:
518               pass
519          else :
520             # Pour les autres types on utilise repr
521             if isinstance(val,Extensions.parametre.PARAMETRE):
522                s = val.nom
523             else:
524                s = `val`
525          s= s + ','
526       return s
527
528
529    def formatColonnes(self,nbrColonnes,text):
530       try :
531       #if 1 == 1 :
532         liste=text.split(",")
533         indice=0
534         textformat=""
535         while ( indice < len(liste) -2  ) :
536           for l in range(nbrColonnes) :
537             textformat=textformat+liste[indice]+","
538             indice=indice+1
539           textformat=textformat+"\n"
540         textformat=textformat+"),"
541       except :
542       #else :
543          textformat=text
544       return textformat