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