Salome HOME
premiere version
[tools/eficas.git] / generator / generator_python.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013   EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20 """
21     Ce module contient le plugin generateur de fichier au format 
22     python pour EFICAS.
23
24 """
25 import traceback
26 import types,string,re
27
28 from Noyau import N_CR
29 from Noyau.N_utils import repr_float
30 import Accas
31 import Extensions
32 from Extensions.parametre import ITEM_PARAMETRE
33 from Formatage import Formatage
34 from Extensions.param2 import Formula
35
36 def entryPoint():
37    """
38        Retourne les informations necessaires pour le chargeur de plugins
39
40        Ces informations sont retournees dans un dictionnaire
41    """
42    return {
43         # Le nom du plugin
44           'name' : 'python',
45         # La factory pour creer une instance du plugin
46           'factory' : PythonGenerator,
47           }
48
49
50 class PythonGenerator:
51    """
52        Ce generateur parcourt un objet de type JDC et produit
53        un fichier au format python 
54
55        L'acquisition et le parcours sont realises par la methode
56        generator.gener(objet_jdc,format)
57
58        L'ecriture du fichier au format ini par appel de la methode
59        generator.writefile(nom_fichier)
60
61        Ses caracteristiques principales sont exposees dans des attributs 
62        de classe :
63          - extensions : qui donne une liste d'extensions de fichier preconisees
64
65    """
66    # Les extensions de fichier preconisees
67    extensions=('.comm',)
68
69    def __init__(self,cr=None):
70       # Si l'objet compte-rendu n'est pas fourni, on utilise le compte-rendu standard
71       if cr :
72          self.cr=cr
73       else:
74          self.cr=N_CR.CR(debut='CR generateur format python pour python',
75                          fin='fin CR format python pour python')
76       # Le texte au format python est stocke dans l'attribut text
77       self.text=''
78       self.appli=None
79
80    def writefile(self,filename):
81       fp=open(filename,'w')
82       fp.write(self.text)
83       fp.close()
84
85    def gener(self,obj,format='brut',config=None):
86       """
87           Retourne une representation du JDC obj sous une
88           forme qui est parametree par format.
89           Si format vaut 'brut', retourne une liste de listes de ...
90           Si format vaut 'standard', retourne un texte obtenu par concatenation de la liste
91           Si format vaut 'beautifie', retourne le meme texte beautifie
92       """
93       self.appli=obj.get_jdc_root().appli
94       #self.appli=obj.appli
95       liste= self.generator(obj)
96       if format == 'brut':
97          self.text=liste
98       elif format == 'standard':
99          self.text=string.join(liste)
100       elif format == 'beautifie':
101          jdc_formate = Formatage(liste,mode='.py')
102          self.text=jdc_formate.formate_jdc()
103       else:
104          raise "Format pas implemente : "+format
105       return self.text
106
107    def generator(self,obj):
108       """
109          Cette methode joue un role d'aiguillage en fonction du type de obj
110          On pourrait utiliser les methodes accept et visitxxx a la 
111          place (depend des gouts !!!)
112       """
113       # ATTENTION a l'ordre des tests : il peut avoir de l'importance (heritage)
114       if isinstance(obj,Accas.PROC_ETAPE):
115          return self.generPROC_ETAPE(obj)
116       # Attention doit etre place avant MACRO (raison : heritage)
117       elif isinstance(obj,Accas.FORM_ETAPE):
118          return self.generFORM_ETAPE(obj)
119       elif isinstance(obj,Accas.MACRO_ETAPE):
120          return self.generMACRO_ETAPE(obj)
121       elif isinstance(obj,Accas.ETAPE):
122          return self.generETAPE(obj)
123       elif isinstance(obj,Accas.MCFACT):
124          return self.generMCFACT(obj)
125       elif isinstance(obj,Accas.MCList):
126          return self.generMCList(obj)
127       elif isinstance(obj,Accas.MCBLOC):
128          return self.generMCBLOC(obj)
129       elif isinstance(obj,Accas.MCSIMP):
130          return self.generMCSIMP(obj)
131       elif isinstance(obj,Accas.ASSD):
132          return self.generASSD(obj)
133       elif isinstance(obj,Accas.ETAPE_NIVEAU):
134          return self.generETAPE_NIVEAU(obj)
135       elif isinstance(obj,Accas.COMMENTAIRE):
136          return self.generCOMMENTAIRE(obj)
137       # Attention doit etre place avant PARAMETRE (raison : heritage)
138       elif isinstance(obj,Accas.PARAMETRE_EVAL):
139          return self.generPARAMETRE_EVAL(obj)
140       elif isinstance(obj,Accas.PARAMETRE):
141          return self.generPARAMETRE(obj)
142       elif isinstance(obj,Accas.EVAL):
143          return self.generEVAL(obj)
144       elif isinstance(obj,Accas.COMMANDE_COMM):
145          return self.generCOMMANDE_COMM(obj)
146       elif isinstance(obj,Accas.JDC):
147          return self.generJDC(obj)
148       elif isinstance(obj,Accas.MCNUPLET):
149          return self.generMCNUPLET(obj)
150       elif isinstance(obj,ITEM_PARAMETRE):
151          return self.generITEM_PARAMETRE(obj)
152       elif isinstance(obj,Formula):
153          return self.generFormula(obj)
154       else:
155          raise "Type d'objet non prevu",obj
156
157    def generJDC(self,obj):
158       """
159          Cette methode convertit un objet JDC en une liste de chaines de
160          caracteres a la syntaxe python
161       """
162       l=[]
163       if obj.definition.l_niveaux == ():
164          # Il n'y a pas de niveaux
165          for etape in obj.etapes:
166             l.append(self.generator(etape))
167       else:
168          # Il y a des niveaux
169          for etape_niveau in obj.etapes_niveaux:
170             l.extend(self.generator(etape_niveau))
171       if l != [] :
172          # Si au moins une etape, on ajoute le retour chariot sur la derniere etape
173          if type(l[-1])==types.ListType:
174             l[-1][-1] = l[-1][-1]+'\n'
175          elif type(l[-1])==types.StringType:
176             l[-1] = l[-1]+'\n'
177       return l
178
179    def generMCNUPLET(self,obj):
180       """ 
181           Methode generant une representation de self permettant son ecriture
182           dans le format python
183       """
184       l=[]
185       l.append('(')
186       for v in obj.mc_liste:
187         text = re.sub(".*=","",self.generator(v))
188         l.append(text)
189       l.append('),')
190       return l
191
192    def generCOMMANDE_COMM(self,obj):
193       """
194          Cette methode convertit un COMMANDE_COMM
195          en une liste de chaines de caracteres a la syntaxe python
196       """
197       l_lignes = string.split(obj.valeur,'\n')
198       txt=''
199       for ligne in l_lignes:
200           txt = txt + '##'+ligne+'\n'
201       return txt
202
203    def generEVAL(self,obj):
204       """
205          Cette methode convertit un EVAL
206          en une liste de chaines de caracteres a la syntaxe python
207       """
208       return 'EVAL("""'+ obj.valeur +'""")'
209
210    def generCOMMENTAIRE(self,obj):
211       """
212          Cette methode convertit un COMMENTAIRE
213          en une liste de chaines de caracteres a la syntaxe python
214       """
215       # modification pour repondre a la demande de C. Durand, d'eviter
216       # l'ajout systematique d'un diese, a la suite du commentaire
217       # Dans la chaine de caracteres obj.valeur, on supprime le dernier
218       # saut de ligne
219       sans_saut = re.sub("\n$","",obj.valeur)
220       l_lignes = string.split(sans_saut,'\n')
221       txt=''
222       i=1
223       for ligne in l_lignes:
224         txt = txt + '#'+ligne+'\n'
225
226       # suppression du dernier saut de ligne
227       #txt = re.sub("\n$","",txt)
228       # on ajoute un saut de ligne avant
229       pattern=re.compile(" ?\#")
230       m=pattern.match(txt)
231       if m:
232          txt="\n"+txt
233       return txt
234
235    def generPARAMETRE_EVAL(self,obj):
236       """
237          Cette methode convertit un PARAMETRE_EVAL
238          en une liste de chaines de caracteres a la syntaxe python
239       """
240       if obj.valeur == None:
241          return obj.nom + ' = None ;\n'
242       else:
243          return obj.nom + ' = '+ self.generator(obj.valeur) +';\n'
244
245    def generITEM_PARAMETRE(self,obj):
246        return repr(obj) 
247
248    def generFormula(self,obj):
249        #return repr(obj) 
250        return str(obj) 
251
252    def generPARAMETRE(self,obj):
253       """
254          Cette methode convertit un PARAMETRE
255          en une liste de chaines de caracteres a la syntaxe python
256       """
257       return repr(obj) + ";\n"
258
259    def generETAPE_NIVEAU(self,obj):
260       """
261          Cette methode convertit une etape niveau
262          en une liste de chaines de caracteres a la syntaxe python
263       """
264       l=[]
265       if obj.etapes_niveaux == []:
266         for etape in obj.etapes:
267           l.append(self.generator(etape))
268       else:
269         for etape_niveau in obj.etapes_niveaux:
270           l.extend(self.generator(etape_niveau))
271       return l
272
273    def generETAPE(self,obj):
274       """
275          Cette methode convertit une etape
276          en une liste de chaines de caracteres a la syntaxe python
277       """
278       try:
279         sdname= self.generator(obj.sd)
280         if  string.find(sdname,'SD_') != -1: sdname='sansnom'
281       except:
282         sdname='sansnom'
283       l=[]
284       label=sdname + '='+obj.definition.nom+'('
285       l.append(label)
286       if obj.reuse != None :
287         str = 'reuse ='+ self.generator(obj.reuse) + ','
288         l.append(str)
289       for v in obj.mc_liste:
290         if isinstance(v,Accas.MCBLOC) :
291           liste=self.generator(v)
292           for mocle in liste :
293             l.append(mocle)
294         elif isinstance(v,Accas.MCSIMP) :
295           text=self.generator(v)
296           l.append(v.nom+'='+text)
297         else:
298           # MCFACT ou MCList
299           liste=self.generator(v)
300           liste[0]=v.nom+'='+liste[0]
301           l.append(liste)
302       if len(l) == 1:
303         l[0]=label+');'
304       else :
305         l.append(');')
306       return l
307
308    def generFORM_ETAPE(self,obj):
309         """
310             Methode particuliere pour les objets de type FORMULE
311         """
312         l=[]
313         nom = obj.get_nom()
314         if nom == '' : nom = 'sansnom'
315         l.append(nom + ' = FORMULE(')
316         for v in obj.mc_liste:
317             text=self.generator(v)
318             l.append(v.nom+'='+text)
319         l.append(');')
320         return l
321
322    def generMACRO_ETAPE(self,obj):
323       """
324          Cette methode convertit une macro-etape
325          en une liste de chaines de caracteres a la syntaxe python
326       """
327       try:
328         if obj.sd == None:
329           sdname=''
330         else:
331           sdname= self.generator(obj.sd)+'='
332       except:
333         sdname='sansnom='
334       l=[]
335       label = sdname + obj.definition.nom+'('
336       l.append(label)
337       if obj.reuse != None:
338          # XXX faut il la virgule ou pas ????
339          str = "reuse =" + self.generator(obj.reuse) + ','
340          l.append(str)
341       for v in obj.mc_liste:
342         if isinstance(v,Accas.MCBLOC) :
343           liste=self.generator(v)
344           for mocle in liste :
345             l.append(mocle)
346         elif isinstance(v,Accas.MCSIMP) :
347           text=self.generator(v)
348           l.append(v.nom+'='+text)
349         else:
350           # MCFACT ou MCList
351           liste=self.generator(v)
352           liste[0]=v.nom+'='+liste[0]
353           l.append(liste)
354
355       if len(l) == 1:
356         l[0]=label+');'
357       else :
358         l.append(');')
359       return l
360
361    def generPROC_ETAPE(self,obj):
362       """
363          Cette methode convertit une PROC etape
364          en une liste de chaines de caracteres a la syntaxe python
365       """
366       l=[]
367       label=obj.definition.nom+'('
368       l.append(label)
369       for v in obj.mc_liste:
370         if isinstance(v,Accas.MCBLOC) :
371           liste=self.generator(v)
372           for mocle in liste :
373             l.append(mocle)
374         elif isinstance(v,Accas.MCSIMP) :
375           text=self.generator(v)
376           l.append(v.nom+'='+text)
377         else:
378           # MCFACT ou MCList
379           liste=self.generator(v)
380           liste[0]=v.nom+'='+liste[0]
381           l.append(liste)
382
383       if len(l) == 1:
384         l[0]=label+');'
385       else :
386         l.append(');')
387       return l
388
389    def generASSD(self,obj):
390       """
391           Convertit un objet derive d'ASSD en une chaine de caracteres a la
392           syntaxe python
393       """
394       return obj.get_name()
395
396    def generMCFACT(self,obj):
397       """
398           Convertit un objet MCFACT en une liste de chaines de caracteres a la
399           syntaxe python
400       """
401       l=[]
402       l.append('_F(')
403       for v in obj.mc_liste:
404          if not isinstance(v,Accas.MCSIMP) and not isinstance (v,Accas.MCBLOC) :
405            # on est en presence d'une entite composee : on recupere une liste
406            liste=self.generator(v)
407            liste[0]=v.nom+'='+liste[0]
408            l.append(liste)
409          elif isinstance(v,Accas.MCBLOC):
410            liste=self.generator(v)
411            for arg in liste :
412              l.append(arg)
413          else:
414            # on est en presence d'un MCSIMP : on recupere une string
415            text =self.generator(v)
416            l.append(v.nom+'='+text)
417            if obj.nom=="Observers": print l
418       # il faut etre plus subtil dans l'ajout de la virgule en differenciant 
419       # le cas ou elle est obligatoire (si self a des freres cadets 
420       # dans self.parent) ou non
421       # (cas ou self est seul ou le benjamin de self.parent)
422       l.append('),')
423       return l
424
425    def generMCList(self,obj):
426       """
427           Convertit un objet MCList en une liste de chaines de caracteres a la
428           syntaxe python
429       """
430       if len(obj.data) > 1:
431          l=['(']
432          for mcfact in obj.data: 
433              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 caracteres a 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
475    def format_item(self,valeur,etape,obj):
476       if (type(valeur) == types.FloatType or 'R' in obj.definition.type) and not(isinstance(valeur,Accas.PARAMETRE)) :
477          # Pour un flottant on utilise str
478          # ou la notation scientifique
479          # On ajoute un . si il n y en a pas dans la valeur
480          s = str(valeur)
481          if (s.find('.')== -1 and s.find('e')== -1 and s.find('E')==-1) : s=s+'.0'
482          clefobj=etape.get_sdname()
483          if self.appli.appliEficas and self.appli.appliEficas.dict_reels.has_key(clefobj):
484            if self.appli.appliEficas.dict_reels[clefobj].has_key(valeur):
485              s=self.appli.appliEficas.dict_reels[clefobj][valeur]
486          
487       elif type(valeur) == types.StringType :
488          if valeur.find('\n') == -1:
489             # pas de retour chariot, on utilise repr
490             s = repr(valeur)
491          elif valeur.find('"""') == -1:
492             # retour chariot mais pas de triple ", on formatte
493             s='"""'+valeur+'"""'
494          else:
495             s = repr(valeur)
496       elif isinstance(valeur,Accas.CO) or hasattr(etape,'sdprods') and valeur in etape.sdprods:
497          s = "CO('"+ self.generator(valeur) +"')"
498       elif isinstance(valeur,Accas.ASSD):
499          s = self.generator(valeur)
500       elif isinstance(valeur,Accas.PARAMETRE):
501          # il ne faut pas prendre la string que retourne gener
502          # mais seulement le nom dans le cas d'un parametre
503          s = valeur.nom
504
505       #elif type(valeur) == types.InstanceType or isinstance(valeur,object):
506       #   if valeur.__class__.__name__ == 'CO' or hasattr(etape,'sdprods') and valeur in etape.sdprods :
507       #      s = "CO('"+ self.generator(valeur) +"')"
508       #   elif isinstance(valeur,Accas.PARAMETRE):
509             # il ne faut pas prendre la string que retourne gener
510             # mais seulement le nom dans le cas d'un parametre
511       #      s = valeur.nom
512       #   else:
513       #      print valeur
514       #      s = self.generator(valeur)
515
516       else :
517          # Pour les autres types on utilise repr
518          s = repr(valeur)
519       return s
520
521    def generMCSIMP(self,obj) :
522       """
523           Convertit un objet MCSIMP en une liste de chaines de caracteres a la
524           syntaxe python
525       """
526       waitTuple=0
527       if type(obj.valeur) in (types.TupleType,types.ListType) :
528          s = ''
529          for ss_type in obj.definition.type:
530           if repr(ss_type).find('Tuple') != -1 :
531              waitTuple=1
532              break
533
534          if waitTuple :
535             s = str(obj.valeur) +','
536             obj.valeurFormatee=obj.valeur
537          else :
538             obj.valeurFormatee=[]
539             for val in obj.valeur :
540                s =s +self.format_item(val,obj.etape,obj) + ','
541                obj.valeurFormatee.append(self.format_item(val,obj.etape,obj))
542             if len(obj.valeur) > 1:
543                s = '(' + s + '),'
544             if obj.valeur==[] : s="(),"
545          if obj.nbrColonnes() :
546             s=self.formatColonnes(obj.nbrColonnes(),obj.valeur,obj)
547       else :
548          obj.valeurFormatee=obj.valeur
549          s=self.format_item(obj.valeur,obj.etape,obj) + ','
550       return s
551
552
553    def formatColonnes(self,nbrColonnes,listeValeurs,obj):
554       #try :
555       print listeValeurs
556       if 1 == 1 :
557         indice=0
558         textformat="("
559         while ( indice < len(listeValeurs) ) :
560           try :
561           #if 1 :
562             for l in range(nbrColonnes) :
563                 texteVariable=self.format_item(listeValeurs[indice],obj.etape,obj)
564                 textformat=textformat+texteVariable+" ,"
565                 indice=indice+1
566             textformat=textformat+"\n"
567           except :
568           #else :
569             while ( indice < len(listeValeurs) ) :
570                 texteVariable=self.format_item(listeValeurs[indice],obj.etape,obj)
571                 textformat=textformat+texteVariable+", "
572                 indice=indice+1
573             textformat=textformat+"\n"
574         textformat=textformat[0:-1]+"),\n"
575       #except :
576       else :
577          textformat=str(obj.valeur)
578       print textformat
579       return textformat