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