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