Salome HOME
PN pour afficher 1 seule fenetre de parametres
[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         l.append(nom + ' = FORMULE(')
300         for v in obj.mc_liste:
301             text=self.generator(v)
302             l.append(v.nom+'='+text)
303         l.append(');')
304         return l
305
306    def generMACRO_ETAPE(self,obj):
307       """
308          Cette méthode convertit une macro-étape
309          en une liste de chaines de caractères à la syntaxe python
310       """
311       if obj.definition.nom == 'FORMULE' : return self.gen_formule(obj)
312       try:
313         if obj.sd == None:
314           sdname=''
315         else:
316           sdname= self.generator(obj.sd)+'='
317       except:
318         sdname='sansnom='
319       l=[]
320       label = sdname + obj.definition.nom+'('
321       l.append(label)
322       if obj.reuse != None:
323          # XXX faut il la virgule ou pas ????
324          str = "reuse =" + self.generator(obj.reuse) + ','
325          l.append(str)
326       for v in obj.mc_liste:
327         if isinstance(v,MCBLOC) :
328           liste=self.generator(v)
329           for mocle in liste :
330             l.append(mocle)
331         elif isinstance(v,MCSIMP) :
332           text=self.generator(v)
333           l.append(v.nom+'='+text)
334         else:
335           # MCFACT ou MCList
336           liste=self.generator(v)
337           liste[0]=v.nom+'='+liste[0]
338           l.append(liste)
339
340       if len(l) == 1:
341         l[0]=label+');'
342       else :
343         l.append(');')
344       return l
345
346    def gen_formule(self,obj):
347       """
348            Méthode particuliere aux objets de type FORMULE
349       """
350       try:
351         if obj.sd == None:
352           sdname=''
353         else:
354           sdname= self.generator(obj.sd)
355       except:
356         sdname='sansnom'
357       l=[]
358       label=sdname + ' = FORMULE('
359       l.append(label)
360       for v in obj.mc_liste:
361         s=''
362         s= v.nom+':'+sdname+'('+v.valeur+')'
363         l.append(s)
364       if len(l) == 1:
365         l[0]=label+');'
366       else :
367         l.append(');')
368       return l
369
370    def generPROC_ETAPE(self,obj):
371       """
372          Cette méthode convertit une PROC étape
373          en une liste de chaines de caractères à la syntaxe python
374       """
375       l=[]
376       label=obj.definition.nom+'('
377       l.append(label)
378       for v in obj.mc_liste:
379         if isinstance(v,MCBLOC) :
380           liste=self.generator(v)
381           for mocle in liste :
382             l.append(mocle)
383         elif isinstance(v,MCSIMP) :
384           text=self.generator(v)
385           l.append(v.nom+'='+text)
386         else:
387           # MCFACT ou MCList
388           liste=self.generator(v)
389           liste[0]=v.nom+'='+liste[0]
390           l.append(liste)
391
392       if len(l) == 1:
393         l[0]=label+');'
394       else :
395         l.append(');')
396       return l
397
398    def generASSD(self,obj):
399       """
400           Convertit un objet dérivé d'ASSD en une chaine de caractères à la
401           syntaxe python
402       """
403       return obj.get_name()
404
405    def generMCFACT(self,obj):
406       """
407           Convertit un objet MCFACT en une liste de chaines de caractères à la
408           syntaxe python
409       """
410       l=[]
411       l.append('_F(')
412       for v in obj.mc_liste:
413          if not isinstance(v,MCSIMP) and not isinstance (v,MCBLOC) :
414            # on est en présence d'une entite composée : on récupère une liste
415            liste=self.generator(v)
416            liste[0]=v.nom+'='+liste[0]
417            l.append(liste)
418          elif isinstance(v,MCBLOC):
419            liste=self.generator(v)
420            for arg in liste :
421              l.append(arg)
422          else:
423            # on est en présence d'un MCSIMP : on récupère une string
424            text =self.generator(v)
425            l.append(v.nom+'='+text)
426       # il faut être plus subtil dans l'ajout de la virgule en différenciant 
427       # le cas où elle est obligatoire (si self a des frères cadets 
428       # dans self.parent) ou non
429       # (cas où self est seul ou le benjamin de self.parent)
430       l.append('),')
431       return l
432
433    def generMCList(self,obj):
434       """
435           Convertit un objet MCList en une liste de chaines de caractères à la
436           syntaxe python
437       """
438       l=[]
439       str =  '('
440       l.append(str)
441       for mcfact in obj.data:
442          l.append(self.generator(mcfact))
443       l.append('),')
444       return l
445
446    def generMCBLOC(self,obj):
447       """
448           Convertit un objet MCBLOC en une liste de chaines de caractères à la
449           syntaxe python
450       """
451       l=[]
452       for v in obj.mc_liste:
453         if isinstance(v,MCBLOC) :
454           liste=self.generator(v)
455           for mocle in liste :
456             l.append(mocle)
457         elif isinstance(v,MCList):
458           liste=self.generator(v)
459           liste[0]=v.nom+'='+liste[0]
460           for mocle in liste :
461             l.append(mocle)
462         else:
463           data=self.generator(v)
464           if type(data) == types.ListType:
465             data[0]=v.nom+'='+data[0]
466           else:
467             data=v.nom+'='+data
468           l.append(data)
469       return l
470
471    def generMCSIMP(self,obj) :
472       """
473           Convertit un objet MCSIMP en une liste de chaines de caractères à la
474           syntaxe python
475       """
476       if type(obj.valeur) in (types.TupleType,types.ListType) :
477          s = ''
478          for val in obj.valeur :
479             if type(val) == types.InstanceType :
480                if hasattr(obj.etape,'sdprods') and val in obj.etape.sdprods :
481                   s = s + "CO('"+ self.generator(val) +"')"
482                elif val.__class__.__name__ == 'CO':
483                   s = s + "CO('"+ self.generator(val) +"')"
484                elif isinstance(val,PARAMETRE):
485                   # il ne faut pas prendre la string que retourne gener
486                   # mais seulement le nom dans le cas d'un paramètre
487                   s = s + val.nom
488                else:
489                   s = s + self.generator(val)
490             elif type(val) == types.FloatType :
491                # Pour un flottant on utilise str qui a une precision de
492                # "seulement" 12 chiffres : evite les flottants du genre 0.599999999999998
493                s = s + str(val)
494             else :
495                # Pour les autres types on utilise repr
496                s = s + `val`
497             s = s + ','
498          if len(obj.valeur) > 1:
499             s = '(' + s + '),'
500       else :
501          val=obj.valeur
502          if type(val) == types.InstanceType :
503             if hasattr(obj.etape,'sdprods') and val in obj.etape.sdprods :
504                s = "CO('"+ self.generator(val) +"')"
505             elif val.__class__.__name__ == 'CO':
506                 s = "CO('"+ self.generator(val) +"')"
507             elif isinstance(val,PARAMETRE):
508                 # il ne faut pas prendre la string que retourne gener
509                 # mais seulement le nom dans le cas d'un paramètre
510                 s = val.nom
511             else:
512                 s = self.generator(val)
513          elif type(val) == types.FloatType :
514             # Pour un flottant on utilise str 
515             s = str(val)
516          else :
517             # Pour les autres types on utilise repr
518             s = `val`
519          s= s + ','
520       return s
521
522