Salome HOME
PN : modif pour integrer les mot-clefs qui dépendent d'autres
[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 from Accas import ETAPE,PROC_ETAPE,MACRO_ETAPE,ETAPE_NIVEAU,JDC,FORM_ETAPE
32 from Accas import MCSIMP,MCFACT,MCBLOC,MCList,EVAL
33 from Accas import GEOM,ASSD,MCNUPLET
34 from Accas import COMMENTAIRE,PARAMETRE, PARAMETRE_EVAL,COMMANDE_COMM
35 from Formatage import Formatage
36
37 def entryPoint():
38    """
39        Retourne les informations nécessaires pour le chargeur de plugins
40
41        Ces informations sont retournées dans un dictionnaire
42    """
43    return {
44         # Le nom du plugin
45           'name' : 'python',
46         # La factory pour créer une instance du plugin
47           'factory' : PythonGenerator,
48           }
49
50
51 class PythonGenerator:
52    """
53        Ce generateur parcourt un objet de type JDC et produit
54        un fichier au format python 
55
56        L'acquisition et le parcours sont réalisés par la méthode
57        generator.gener(objet_jdc,format)
58
59        L'écriture du fichier au format ini par appel de la méthode
60        generator.writefile(nom_fichier)
61
62        Ses caractéristiques principales sont exposées dans des attributs 
63        de classe :
64          - extensions : qui donne une liste d'extensions de fichier préconisées
65
66    """
67    # Les extensions de fichier préconisées
68    extensions=('.comm',)
69
70    def __init__(self,cr=None):
71       # Si l'objet compte-rendu n'est pas fourni, on utilise le compte-rendu standard
72       if cr :
73          self.cr=cr
74       else:
75          self.cr=N_CR.CR(debut='CR generateur format python pour python',
76                          fin='fin CR format python pour python')
77       # Le texte au format python est stocké dans l'attribut text
78       self.text=''
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       liste= self.generator(obj)
94       if format == 'brut':
95          self.text=liste
96       elif format == 'standard':
97          self.text=string.join(liste)
98       elif format == 'beautifie':
99          jdc_formate = Formatage(liste,mode='.py')
100          self.text=jdc_formate.formate_jdc()
101       else:
102          raise "Format pas implémenté : "+format
103       return self.text
104
105    def generator(self,obj):
106       """
107          Cette methode joue un role d'aiguillage en fonction du type de obj
108          On pourrait utiliser les méthodes accept et visitxxx à la 
109          place (dépend des gouts !!!)
110       """
111       # ATTENTION a l'ordre des tests : il peut avoir de l'importance (héritage)
112       if isinstance(obj,PROC_ETAPE):
113          return self.generPROC_ETAPE(obj)
114       elif isinstance(obj,MACRO_ETAPE):
115          return self.generMACRO_ETAPE(obj)
116       elif isinstance(obj,FORM_ETAPE):
117          return self.generFORM_ETAPE(obj)
118       elif isinstance(obj,ETAPE):
119          return self.generETAPE(obj)
120       elif isinstance(obj,MCFACT):
121          return self.generMCFACT(obj)
122       elif isinstance(obj,MCList):
123          return self.generMCList(obj)
124       elif isinstance(obj,MCBLOC):
125          return self.generMCBLOC(obj)
126       elif isinstance(obj,MCSIMP):
127          return self.generMCSIMP(obj)
128       elif isinstance(obj,ASSD):
129          return self.generASSD(obj)
130       elif isinstance(obj,ETAPE_NIVEAU):
131          return self.generETAPE_NIVEAU(obj)
132       elif isinstance(obj,COMMENTAIRE):
133          return self.generCOMMENTAIRE(obj)
134       # Attention doit etre placé avant PARAMETRE (raison : héritage)
135       elif isinstance(obj,PARAMETRE_EVAL):
136          return self.generPARAMETRE_EVAL(obj)
137       elif isinstance(obj,PARAMETRE):
138          return self.generPARAMETRE(obj)
139       elif isinstance(obj,EVAL):
140          return self.generEVAL(obj)
141       elif isinstance(obj,COMMANDE_COMM):
142          return self.generCOMMANDE_COMM(obj)
143       elif isinstance(obj,JDC):
144          return self.generJDC(obj)
145       elif isinstance(obj,MCNUPLET):
146          return self.generMCNUPLET(obj)
147       else:
148          raise "Type d'objet non prévu",obj
149
150    def generJDC(self,obj):
151       """
152          Cette méthode convertit un objet JDC en une liste de chaines de
153          caractères à la syntaxe python
154       """
155       l=[]
156       if obj.definition.l_niveaux == ():
157          # Il n'y a pas de niveaux
158          for etape in obj.etapes:
159             l.append(self.generator(etape))
160       else:
161          # Il y a des niveaux
162          for etape_niveau in obj.etapes_niveaux:
163             l.extend(self.generator(etape_niveau))
164       if l != [] :
165          # Si au moins une étape, on ajoute le retour chariot sur la dernière étape
166          if type(l[-1])==types.ListType:
167             l[-1][-1] = l[-1][-1]+'\n'
168          elif type(l[-1])==types.StringType:
169             l[-1] = l[-1]+'\n'
170       return l
171
172    def generMCNUPLET(self,obj):
173       """ 
174           Méthode générant une représentation de self permettant son ecriture
175           dans le format python
176       """
177       l=[]
178       l.append('(')
179       for v in obj.mc_liste:
180         text = re.sub(".*=","",self.generator(v))
181         l.append(text)
182       l.append('),')
183       return l
184
185    def generCOMMANDE_COMM(self,obj):
186       """
187          Cette méthode convertit un COMMANDE_COMM
188          en une liste de chaines de caractères à la syntaxe python
189       """
190       l_lignes = string.split(obj.valeur,'\n')
191       txt=''
192       for ligne in l_lignes:
193           txt = txt + '##'+ligne+'\n'
194       return txt
195
196    def generEVAL(self,obj):
197       """
198          Cette méthode convertit un EVAL
199          en une liste de chaines de caractères à la syntaxe python
200       """
201       return 'EVAL("""'+ obj.valeur +'""")'
202
203    def generCOMMENTAIRE(self,obj):
204       """
205          Cette méthode convertit un COMMENTAIRE
206          en une liste de chaines de caractères à la syntaxe python
207       """
208       # modification pour répondre à la demande de C. Durand, d'éviter
209       # l'ajout systématique d'un dièse, à la suite du commentaire
210       # Dans la chaine de caracteres obj.valeur, on supprime le dernier
211       # saut de ligne
212       sans_saut = re.sub("\n$","",obj.valeur)
213       l_lignes = string.split(sans_saut,'\n')
214       txt=''
215       for ligne in l_lignes:
216         txt = txt + '#'+ligne+'\n'
217
218       # suppression du dernier saut de ligne
219       txt = re.sub("\n$","",txt)
220       return txt
221
222    def generPARAMETRE_EVAL(self,obj):
223       """
224          Cette méthode convertit un PARAMETRE_EVAL
225          en une liste de chaines de caractères à la syntaxe python
226       """
227       if obj.valeur == None:
228          return obj.nom + ' = None ;\n'
229       else:
230          return obj.nom + ' = '+ self.generator(obj.valeur) +';\n'
231
232    def generPARAMETRE(self,obj):
233       """
234          Cette méthode convertit un PARAMETRE
235          en une liste de chaines de caractères à la syntaxe python
236       """
237       if type(obj.valeur) == types.StringType:
238         # PN pour corriger le bug a='3+4' au lieu de a= 3+4
239         #return obj.nom + " = '" + obj.valeur + "';\n"
240         return obj.nom + " = " + obj.valeur + ";\n"
241       else:
242         return obj.nom + ' = ' + str(obj.valeur) + ';\n'
243
244    def generETAPE_NIVEAU(self,obj):
245       """
246          Cette méthode convertit une étape niveau
247          en une liste de chaines de caractères à la syntaxe python
248       """
249       l=[]
250       if obj.etapes_niveaux == []:
251         for etape in obj.etapes:
252           l.append(self.generator(etape))
253       else:
254         for etape_niveau in obj.etapes_niveaux:
255           l.extend(self.generator(etape_niveau))
256       return l
257
258    def generETAPE(self,obj):
259       """
260          Cette méthode convertit une étape
261          en une liste de chaines de caractères à la syntaxe python
262       """
263       try:
264         sdname= self.generator(obj.sd)
265       except:
266         sdname='sansnom'
267       l=[]
268       label=sdname + '='+obj.definition.nom+'('
269       l.append(label)
270       if obj.reuse != None :
271         str = 'reuse ='+ self.generator(obj.reuse) + ','
272         l.append(str)
273       for v in obj.mc_liste:
274         if isinstance(v,MCBLOC) :
275           liste=self.generator(v)
276           for mocle in liste :
277             l.append(mocle)
278         elif isinstance(v,MCSIMP) :
279           text=self.generator(v)
280           l.append(v.nom+'='+text)
281         else:
282           # MCFACT ou MCList
283           liste=self.generator(v)
284           liste[0]=v.nom+'='+liste[0]
285           l.append(liste)
286       if len(l) == 1:
287         l[0]=label+');'
288       else :
289         l.append(');')
290       return l
291
292    def generFORM_ETAPE(self,obj):
293         """
294             Méthode particulière pour les objets de type FORMULE
295         """
296         l=[]
297         nom = obj.get_nom()
298         if nom == '' : nom = 'sansnom'
299         if len(obj.mc_liste)>0:
300             l.append(nom + ' = FORMULE(')
301             s=obj.type_retourne + ' = ' + "'''" + obj.arguments + ' = ' + obj.corps+"'''"
302             l.append(s)
303             l.append(');')
304         else:
305             l.append(nom+' = FORMULE();')
306         return l
307
308    def generMACRO_ETAPE(self,obj):
309       """
310          Cette méthode convertit une macro-étape
311          en une liste de chaines de caractères à la syntaxe python
312       """
313       if obj.definition.nom == 'FORMULE' : return self.gen_formule(obj)
314       try:
315         if obj.sd == None:
316           sdname=''
317         else:
318           sdname= self.generator(obj.sd)+'='
319       except:
320         sdname='sansnom='
321       l=[]
322       label = sdname + obj.definition.nom+'('
323       l.append(label)
324       if obj.reuse != None:
325          # XXX faut il la virgule ou pas ????
326          str = "reuse =" + self.generator(obj.reuse) + ','
327          l.append(str)
328       for v in obj.mc_liste:
329         if isinstance(v,MCBLOC) :
330           liste=self.generator(v)
331           for mocle in liste :
332             l.append(mocle)
333         elif isinstance(v,MCSIMP) :
334           text=self.generator(v)
335           l.append(v.nom+'='+text)
336         else:
337           # MCFACT ou MCList
338           liste=self.generator(v)
339           liste[0]=v.nom+'='+liste[0]
340           l.append(liste)
341
342       if len(l) == 1:
343         l[0]=label+');'
344       else :
345         l.append(');')
346       return l
347
348    def gen_formule(self,obj):
349       """
350            Méthode particuliere aux objets de type FORMULE
351       """
352       try:
353         if obj.sd == None:
354           sdname=''
355         else:
356           sdname= self.generator(obj.sd)
357       except:
358         sdname='sansnom'
359       l=[]
360       label=sdname + ' = FORMULE('
361       l.append(label)
362       for v in obj.mc_liste:
363         s=''
364         s= v.nom+':'+sdname+'('+v.valeur+')'
365         l.append(s)
366       if len(l) == 1:
367         l[0]=label+');'
368       else :
369         l.append(');')
370       return l
371
372    def generPROC_ETAPE(self,obj):
373       """
374          Cette méthode convertit une PROC étape
375          en une liste de chaines de caractères à la syntaxe python
376       """
377       l=[]
378       label=obj.definition.nom+'('
379       l.append(label)
380       for v in obj.mc_liste:
381         if isinstance(v,MCBLOC) :
382           liste=self.generator(v)
383           for mocle in liste :
384             l.append(mocle)
385         elif isinstance(v,MCSIMP) :
386           text=self.generator(v)
387           l.append(v.nom+'='+text)
388         else:
389           # MCFACT ou MCList
390           liste=self.generator(v)
391           liste[0]=v.nom+'='+liste[0]
392           l.append(liste)
393
394       if len(l) == 1:
395         l[0]=label+');'
396       else :
397         l.append(');')
398       return l
399
400    def generASSD(self,obj):
401       """
402           Convertit un objet dérivé d'ASSD en une chaine de caractères à la
403           syntaxe python
404       """
405       return obj.get_name()
406
407    def generMCFACT(self,obj):
408       """
409           Convertit un objet MCFACT en une liste de chaines de caractères à la
410           syntaxe python
411       """
412       l=[]
413       l.append('_F(')
414       for v in obj.mc_liste:
415          if not isinstance(v,MCSIMP) and not isinstance (v,MCBLOC) :
416            # on est en présence d'une entite composée : on récupère une liste
417            liste=self.generator(v)
418            liste[0]=v.nom+'='+liste[0]
419            l.append(liste)
420          elif isinstance(v,MCBLOC):
421            liste=self.generator(v)
422            for arg in liste :
423              l.append(arg)
424          else:
425            # on est en présence d'un MCSIMP : on récupère une string
426            text =self.generator(v)
427            l.append(v.nom+'='+text)
428       # il faut être plus subtil dans l'ajout de la virgule en différenciant 
429       # le cas où elle est obligatoire (si self a des frères cadets 
430       # dans self.parent) ou non
431       # (cas où self est seul ou le benjamin de self.parent)
432       l.append('),')
433       return l
434
435    def generMCList(self,obj):
436       """
437           Convertit un objet MCList en une liste de chaines de caractères à la
438           syntaxe python
439       """
440       l=[]
441       str =  '('
442       l.append(str)
443       for mcfact in obj.data:
444          l.append(self.generator(mcfact))
445       l.append('),')
446       return l
447
448    def generMCBLOC(self,obj):
449       """
450           Convertit un objet MCBLOC en une liste de chaines de caractères à la
451           syntaxe python
452       """
453       l=[]
454       for v in obj.mc_liste:
455         if isinstance(v,MCBLOC) :
456           liste=self.generator(v)
457           for mocle in liste :
458             l.append(mocle)
459         elif isinstance(v,MCList):
460           liste=self.generator(v)
461           liste[0]=v.nom+'='+liste[0]
462           for mocle in liste :
463             l.append(mocle)
464         else:
465           data=self.generator(v)
466           if type(data) == types.ListType:
467             data[0]=v.nom+'='+data[0]
468           else:
469             data=v.nom+'='+data
470           l.append(data)
471       return l
472
473    def generMCSIMP(self,obj) :
474       """
475           Convertit un objet MCSIMP en une liste de chaines de caractères à la
476           syntaxe python
477       """
478       if type(obj.valeur) in (types.TupleType,types.ListType) :
479          s = ''
480          for val in obj.valeur :
481             if type(val) == types.InstanceType :
482                if hasattr(obj.etape,'sdprods') and val in obj.etape.sdprods :
483                   s = s + "CO('"+ self.generator(val) +"')"
484                elif val.__class__.__name__ == 'CO':
485                   s = s + "CO('"+ self.generator(val) +"')"
486                elif isinstance(val,PARAMETRE):
487                   # il ne faut pas prendre la string que retourne gener
488                   # mais seulement le nom dans le cas d'un paramètre
489                   s = s + val.nom
490                else:
491                   s = s + self.generator(val)
492             elif type(val) == types.FloatType :
493                # Pour un flottant on utilise str qui a une precision de
494                # "seulement" 12 chiffres : evite les flottants du genre 0.599999999999998
495                s = s + str(val)
496             else :
497                # Pour les autres types on utilise repr
498                s = s + `val`
499             s = s + ','
500          if len(obj.valeur) > 1:
501             s = '(' + s + '),'
502       else :
503          val=obj.valeur
504          if type(val) == types.InstanceType :
505             if hasattr(obj.etape,'sdprods') and val in obj.etape.sdprods :
506                s = "CO('"+ self.generator(val) +"')"
507             elif val.__class__.__name__ == 'CO':
508                 s = "CO('"+ self.generator(val) +"')"
509             elif isinstance(val,PARAMETRE):
510                 # il ne faut pas prendre la string que retourne gener
511                 # mais seulement le nom dans le cas d'un paramètre
512                 s = val.nom
513             else:
514                 s = self.generator(val)
515          elif type(val) == types.FloatType :
516             # Pour un flottant on utilise str 
517             s = str(val)
518          else :
519             # Pour les autres types on utilise repr
520             s = `val`
521          s= s + ','
522       return s
523
524