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