Salome HOME
PN pour notation scientifique
[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       self.appli=None
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       self.appli=obj.appli
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,Accas.PROC_ETAPE):
113          return self.generPROC_ETAPE(obj)
114       # Attention doit etre placé avant MACRO (raison : héritage)
115       elif isinstance(obj,Accas.FORM_ETAPE):
116          return self.generFORM_ETAPE(obj)
117       elif isinstance(obj,Accas.MACRO_ETAPE):
118          return self.generMACRO_ETAPE(obj)
119       elif isinstance(obj,Accas.ETAPE):
120          return self.generETAPE(obj)
121       elif isinstance(obj,Accas.MCFACT):
122          return self.generMCFACT(obj)
123       elif isinstance(obj,Accas.MCList):
124          return self.generMCList(obj)
125       elif isinstance(obj,Accas.MCBLOC):
126          return self.generMCBLOC(obj)
127       elif isinstance(obj,Accas.MCSIMP):
128          return self.generMCSIMP(obj)
129       elif isinstance(obj,Accas.ASSD):
130          return self.generASSD(obj)
131       elif isinstance(obj,Accas.ETAPE_NIVEAU):
132          return self.generETAPE_NIVEAU(obj)
133       elif isinstance(obj,Accas.COMMENTAIRE):
134          return self.generCOMMENTAIRE(obj)
135       # Attention doit etre placé avant PARAMETRE (raison : héritage)
136       elif isinstance(obj,Accas.PARAMETRE_EVAL):
137          return self.generPARAMETRE_EVAL(obj)
138       elif isinstance(obj,Accas.PARAMETRE):
139          return self.generPARAMETRE(obj)
140       elif isinstance(obj,Accas.EVAL):
141          return self.generEVAL(obj)
142       elif isinstance(obj,Accas.COMMANDE_COMM):
143          return self.generCOMMANDE_COMM(obj)
144       elif isinstance(obj,Accas.JDC):
145          return self.generJDC(obj)
146       elif isinstance(obj,Accas.MCNUPLET):
147          return self.generMCNUPLET(obj)
148       elif isinstance(obj,ITEM_PARAMETRE):
149          return self.generITEM_PARAMETRE(obj)
150       else:
151          raise "Type d'objet non prévu",obj
152
153    def generJDC(self,obj):
154       """
155          Cette méthode convertit un objet JDC en une liste de chaines de
156          caractères à la syntaxe python
157       """
158       l=[]
159       if obj.definition.l_niveaux == ():
160          # Il n'y a pas de niveaux
161          for etape in obj.etapes:
162             l.append(self.generator(etape))
163       else:
164          # Il y a des niveaux
165          for etape_niveau in obj.etapes_niveaux:
166             l.extend(self.generator(etape_niveau))
167       if l != [] :
168          # Si au moins une étape, on ajoute le retour chariot sur la dernière étape
169          if type(l[-1])==types.ListType:
170             l[-1][-1] = l[-1][-1]+'\n'
171          elif type(l[-1])==types.StringType:
172             l[-1] = l[-1]+'\n'
173       return l
174
175    def generMCNUPLET(self,obj):
176       """ 
177           Méthode générant une représentation de self permettant son ecriture
178           dans le format python
179       """
180       l=[]
181       l.append('(')
182       for v in obj.mc_liste:
183         text = re.sub(".*=","",self.generator(v))
184         l.append(text)
185       l.append('),')
186       return l
187
188    def generCOMMANDE_COMM(self,obj):
189       """
190          Cette méthode convertit un COMMANDE_COMM
191          en une liste de chaines de caractères à la syntaxe python
192       """
193       l_lignes = string.split(obj.valeur,'\n')
194       txt=''
195       for ligne in l_lignes:
196           txt = txt + '##'+ligne+'\n'
197       return txt
198
199    def generEVAL(self,obj):
200       """
201          Cette méthode convertit un EVAL
202          en une liste de chaines de caractères à la syntaxe python
203       """
204       return 'EVAL("""'+ obj.valeur +'""")'
205
206    def generCOMMENTAIRE(self,obj):
207       """
208          Cette méthode convertit un COMMENTAIRE
209          en une liste de chaines de caractères à la syntaxe python
210       """
211       # modification pour répondre à la demande de C. Durand, d'éviter
212       # l'ajout systématique d'un dièse, à la suite du commentaire
213       # Dans la chaine de caracteres obj.valeur, on supprime le dernier
214       # saut de ligne
215       sans_saut = re.sub("\n$","",obj.valeur)
216       l_lignes = string.split(sans_saut,'\n')
217       txt=''
218       for ligne in l_lignes:
219         txt = txt + '#'+ligne+'\n'
220
221       # suppression du dernier saut de ligne
222       txt = re.sub("\n$","",txt)
223       return txt
224
225    def generPARAMETRE_EVAL(self,obj):
226       """
227          Cette méthode convertit un PARAMETRE_EVAL
228          en une liste de chaines de caractères à la syntaxe python
229       """
230       if obj.valeur == None:
231          return obj.nom + ' = None ;\n'
232       else:
233          return obj.nom + ' = '+ self.generator(obj.valeur) +';\n'
234
235    def generITEM_PARAMETRE(self,obj):
236        return repr(obj) 
237
238    def generPARAMETRE(self,obj):
239       """
240          Cette méthode convertit un PARAMETRE
241          en une liste de chaines de caractères à la syntaxe python
242       """
243       if type(obj.valeur) == types.StringType:
244         # PN pour corriger le bug a='3+4' au lieu de a= 3+4
245         #return obj.nom + " = '" + obj.valeur + "';\n"
246         return obj.nom + " = " + obj.valeur + ";\n"
247       else:
248         return obj.nom + ' = ' + str(obj.valeur) + ';\n'
249
250    def generETAPE_NIVEAU(self,obj):
251       """
252          Cette méthode convertit une étape niveau
253          en une liste de chaines de caractères à la syntaxe python
254       """
255       l=[]
256       if obj.etapes_niveaux == []:
257         for etape in obj.etapes:
258           l.append(self.generator(etape))
259       else:
260         for etape_niveau in obj.etapes_niveaux:
261           l.extend(self.generator(etape_niveau))
262       return l
263
264    def generETAPE(self,obj):
265       """
266          Cette méthode convertit une étape
267          en une liste de chaines de caractères à la syntaxe python
268       """
269       try:
270         sdname= self.generator(obj.sd)
271       except:
272         sdname='sansnom'
273       l=[]
274       label=sdname + '='+obj.definition.nom+'('
275       l.append(label)
276       if obj.reuse != None :
277         str = 'reuse ='+ self.generator(obj.reuse) + ','
278         l.append(str)
279       for v in obj.mc_liste:
280         if isinstance(v,Accas.MCBLOC) :
281           liste=self.generator(v)
282           for mocle in liste :
283             l.append(mocle)
284         elif isinstance(v,Accas.MCSIMP) :
285           text=self.generator(v)
286           l.append(v.nom+'='+text)
287         else:
288           # MCFACT ou MCList
289           liste=self.generator(v)
290           liste[0]=v.nom+'='+liste[0]
291           l.append(liste)
292       if len(l) == 1:
293         l[0]=label+');'
294       else :
295         l.append(');')
296       return l
297
298    def generFORM_ETAPE(self,obj):
299         """
300             Méthode particulière pour les objets de type FORMULE
301         """
302         l=[]
303         nom = obj.get_nom()
304         if nom == '' : nom = 'sansnom'
305         l.append(nom + ' = FORMULE(')
306         for v in obj.mc_liste:
307             text=self.generator(v)
308             l.append(v.nom+'='+text)
309         l.append(');')
310         return l
311
312    def generMACRO_ETAPE(self,obj):
313       """
314          Cette méthode convertit une macro-étape
315          en une liste de chaines de caractères à la syntaxe python
316       """
317       try:
318         if obj.sd == None:
319           sdname=''
320         else:
321           sdname= self.generator(obj.sd)+'='
322       except:
323         sdname='sansnom='
324       l=[]
325       label = sdname + obj.definition.nom+'('
326       l.append(label)
327       if obj.reuse != None:
328          # XXX faut il la virgule ou pas ????
329          str = "reuse =" + self.generator(obj.reuse) + ','
330          l.append(str)
331       for v in obj.mc_liste:
332         if isinstance(v,Accas.MCBLOC) :
333           liste=self.generator(v)
334           for mocle in liste :
335             l.append(mocle)
336         elif isinstance(v,Accas.MCSIMP) :
337           text=self.generator(v)
338           l.append(v.nom+'='+text)
339         else:
340           # MCFACT ou MCList
341           liste=self.generator(v)
342           liste[0]=v.nom+'='+liste[0]
343           l.append(liste)
344
345       if len(l) == 1:
346         l[0]=label+');'
347       else :
348         l.append(');')
349       return l
350
351    def generPROC_ETAPE(self,obj):
352       """
353          Cette méthode convertit une PROC étape
354          en une liste de chaines de caractères à la syntaxe python
355       """
356       l=[]
357       label=obj.definition.nom+'('
358       l.append(label)
359       for v in obj.mc_liste:
360         if isinstance(v,Accas.MCBLOC) :
361           liste=self.generator(v)
362           for mocle in liste :
363             l.append(mocle)
364         elif isinstance(v,Accas.MCSIMP) :
365           text=self.generator(v)
366           l.append(v.nom+'='+text)
367         else:
368           # MCFACT ou MCList
369           liste=self.generator(v)
370           liste[0]=v.nom+'='+liste[0]
371           l.append(liste)
372
373       if len(l) == 1:
374         l[0]=label+');'
375       else :
376         l.append(');')
377       return l
378
379    def generASSD(self,obj):
380       """
381           Convertit un objet dérivé d'ASSD en une chaine de caractères à la
382           syntaxe python
383       """
384       return obj.get_name()
385
386    def generMCFACT(self,obj):
387       """
388           Convertit un objet MCFACT en une liste de chaines de caractères à la
389           syntaxe python
390       """
391       l=[]
392       l.append('_F(')
393       for v in obj.mc_liste:
394          if not isinstance(v,Accas.MCSIMP) and not isinstance (v,Accas.MCBLOC) :
395            # on est en présence d'une entite composée : on récupère une liste
396            liste=self.generator(v)
397            liste[0]=v.nom+'='+liste[0]
398            l.append(liste)
399          elif isinstance(v,Accas.MCBLOC):
400            liste=self.generator(v)
401            for arg in liste :
402              l.append(arg)
403          else:
404            # on est en présence d'un MCSIMP : on récupère une string
405            text =self.generator(v)
406            l.append(v.nom+'='+text)
407       # il faut être plus subtil dans l'ajout de la virgule en différenciant 
408       # le cas où elle est obligatoire (si self a des frères cadets 
409       # dans self.parent) ou non
410       # (cas où self est seul ou le benjamin de self.parent)
411       l.append('),')
412       return l
413
414    def generMCList(self,obj):
415       """
416           Convertit un objet MCList en une liste de chaines de caractères à la
417           syntaxe python
418       """
419       if len(obj.data) > 1:
420          l=['(']
421          for mcfact in obj.data: l.append(self.generator(mcfact))
422          l.append('),')
423       else:
424          l= self.generator(obj.data[0])
425       return l
426
427    def generMCBLOC(self,obj):
428       """
429           Convertit un objet MCBLOC en une liste de chaines de caractères à la
430           syntaxe python
431       """
432       l=[]
433       for v in obj.mc_liste:
434         if isinstance(v,Accas.MCBLOC) :
435           liste=self.generator(v)
436           for mocle in liste :
437             l.append(mocle)
438         elif isinstance(v,Accas.MCList):
439           liste=self.generator(v)
440           liste[0]=v.nom+'='+liste[0]
441           for mocle in liste :
442             l.append(mocle)
443         else:
444           data=self.generator(v)
445           if type(data) == types.ListType:
446             data[0]=v.nom+'='+data[0]
447           else:
448             data=v.nom+'='+data
449           l.append(data)
450       return l
451
452    def generMCSIMP(self,obj) :
453       """
454           Convertit un objet MCSIMP en une liste de chaines de caractères à la
455           syntaxe python
456       """
457       if type(obj.valeur) in (types.TupleType,types.ListType) :
458          s = ''
459          for val in obj.valeur :
460             if type(val) == types.InstanceType :
461                if hasattr(obj.etape,'sdprods') and val in obj.etape.sdprods :
462                   s = s + "CO('"+ self.generator(val) +"')"
463                elif val.__class__.__name__ == 'CO':
464                   s = s + "CO('"+ self.generator(val) +"')"
465                elif isinstance(val,Accas.PARAMETRE):
466                   # il ne faut pas prendre la string que retourne gener
467                   # mais seulement le nom dans le cas d'un paramètre
468                   s = s + val.nom
469                else:
470                   s = s + self.generator(val)
471             elif type(val) == types.FloatType :
472                # Pour un flottant on utilise str qui a une precision de
473                # "seulement" 12 chiffres : evite les flottants du genre 0.599999999999998
474                s = s + str(val)
475             else :
476                # Pour les autres types on utilise repr
477                s = s + `val`
478             s = s + ','
479          if len(obj.valeur) > 1:
480             s = '(' + s + '),'
481       else :
482          val=obj.valeur
483          if type(val) == types.InstanceType :
484             if hasattr(obj.etape,'sdprods') and val in obj.etape.sdprods :
485                s = "CO('"+ self.generator(val) +"')"
486             elif val.__class__.__name__ == 'CO':
487                 s = "CO('"+ self.generator(val) +"')"
488             elif isinstance(val,Accas.PARAMETRE):
489                 # il ne faut pas prendre la string que retourne gener
490                 # mais seulement le nom dans le cas d'un paramètre
491                 s = val.nom
492             else:
493                 s = self.generator(val)
494          elif type(val) == types.FloatType :
495             # Pour un flottant on utilise str 
496             # ou la notation scientifique
497             try :
498               clefobj=obj.GetNomConcept()
499               if self.parent.appli.dict_reels.has_key(clefobj):
500                  if self.parent.appli.dict_reels[clefobj].has_key(val):
501                     s=self.parent.appli.dict_reels[clefobj][val]
502             except:
503                s = str(val)
504          else :
505             # Pour les autres types on utilise repr
506             s = `val`
507          s= s + ','
508       return s
509
510