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