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