Salome HOME
mse a jour du 07/03/2016 pour sauvegarde
[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):
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       print format
100       liste= self.generator(obj)
101       if format == 'brut':
102          self.text=liste
103       elif format == 'standard':
104          self.text=string.join(liste)
105       elif format == 'beautifie':
106          jdc_formate = Formatage(liste,mode='.py')
107          self.text=jdc_formate.formate_jdc()
108       elif format == 'Ligne':
109          jdc_formate = FormatageLigne(liste,mode='.py')
110          self.text=jdc_formate.formate_jdc()
111       else:
112          raise EficasException(tr("Format non implemente ") +format)
113       return self.text
114
115    def generator(self,obj):
116       """
117          Cette methode joue un role d'aiguillage en fonction du type de obj
118          On pourrait utiliser les methodes accept et visitxxx a la 
119          place (depend des gouts !!!)
120       """
121       # ATTENTION a l'ordre des tests : il peut avoir de l'importance (heritage)
122       if isinstance(obj,Accas.PROC_ETAPE):
123          return self.generPROC_ETAPE(obj)
124       # Attention doit etre place avant MACRO (raison : heritage)
125       elif isinstance(obj,Accas.FORM_ETAPE):
126          return self.generFORM_ETAPE(obj)
127       elif isinstance(obj,Accas.MACRO_ETAPE):
128          return self.generMACRO_ETAPE(obj)
129       elif isinstance(obj,Accas.ETAPE):
130          return self.generETAPE(obj)
131       elif isinstance(obj,Accas.MCFACT):
132          return self.generMCFACT(obj)
133       elif isinstance(obj,Accas.MCList):
134          return self.generMCList(obj)
135       elif isinstance(obj,Accas.MCBLOC):
136          return self.generMCBLOC(obj)
137       elif isinstance(obj,Accas.MCSIMP):
138          return self.generMCSIMP(obj)
139       elif isinstance(obj,Accas.ASSD):
140          return self.generASSD(obj)
141       elif isinstance(obj,Accas.ETAPE_NIVEAU):
142          return self.generETAPE_NIVEAU(obj)
143       elif isinstance(obj,Accas.COMMENTAIRE):
144          return self.generCOMMENTAIRE(obj)
145       # Attention doit etre place avant PARAMETRE (raison : heritage)
146       elif isinstance(obj,Accas.PARAMETRE_EVAL):
147          return self.generPARAMETRE_EVAL(obj)
148       elif isinstance(obj,Accas.PARAMETRE):
149          return self.generPARAMETRE(obj)
150       elif isinstance(obj,Accas.EVAL):
151          return self.generEVAL(obj)
152       elif isinstance(obj,Accas.COMMANDE_COMM):
153          return self.generCOMMANDE_COMM(obj)
154       elif isinstance(obj,Accas.JDC):
155          return self.generJDC(obj)
156       elif isinstance(obj,Accas.MCNUPLET):
157          return self.generMCNUPLET(obj)
158       elif isinstance(obj,ITEM_PARAMETRE):
159          return self.generITEM_PARAMETRE(obj)
160       elif isinstance(obj,Formula):
161          return self.generFormula(obj)
162       else:
163          raise EficasException(tr("Type d'objet non prevu") +obj)
164
165    def generJDC(self,obj):
166       """
167          Cette methode convertit un objet JDC en une liste de chaines de
168          caracteres a la syntaxe python
169       """
170       l=[]
171       if obj.definition.l_niveaux == ():
172          # Il n'y a pas de niveaux
173          for etape in obj.etapes:
174             l.append(self.generator(etape))
175       else:
176          # Il y a des niveaux
177          for etape_niveau in obj.etapes_niveaux:
178             l.extend(self.generator(etape_niveau))
179       if l != [] :
180          # Si au moins une etape, on ajoute le retour chariot sur la derniere etape
181          if type(l[-1])==types.ListType:
182             l[-1][-1] = l[-1][-1]+'\n'
183          elif type(l[-1])==types.StringType:
184             l[-1] = l[-1]+'\n'
185       return l
186
187    def generMCNUPLET(self,obj):
188       """ 
189           Methode generant une representation de self permettant son ecriture
190           dans le format python
191       """
192       l=[]
193       l.append('(')
194       for v in obj.mc_liste:
195         text = re.sub(".*=","",self.generator(v))
196         l.append(text)
197       l.append('),')
198       return l
199
200    def generCOMMANDE_COMM(self,obj):
201       """
202          Cette methode convertit un COMMANDE_COMM
203          en une liste de chaines de caracteres a la syntaxe python
204       """
205       l_lignes = string.split(obj.valeur,'\n')
206       txt=''
207       for ligne in l_lignes:
208           txt = txt + '##'+ligne+'\n'
209       return txt
210
211    def generEVAL(self,obj):
212       """
213          Cette methode convertit un EVAL
214          en une liste de chaines de caracteres a la syntaxe python
215       """
216       return 'EVAL("""'+ obj.valeur +'""")'
217
218    def generCOMMENTAIRE(self,obj):
219       """
220          Cette methode convertit un COMMENTAIRE
221          en une liste de chaines de caracteres a la syntaxe python
222       """
223       # modification pour repondre a la demande de C. Durand, d'eviter
224       # l'ajout systematique d'un diese, a la suite du commentaire
225       # Dans la chaine de caracteres obj.valeur, on supprime le dernier
226       # saut de ligne
227       sans_saut = re.sub("\n$","",obj.valeur)
228       l_lignes = string.split(sans_saut,'\n')
229       txt=''
230       i=1
231       for ligne in l_lignes:
232         txt = txt + '#'+ligne+'\n'
233
234       # suppression du dernier saut de ligne
235       #txt = re.sub("\n$","",txt)
236       # on ajoute un saut de ligne avant
237       pattern=re.compile(" ?\#")
238       m=pattern.match(txt)
239       if m:
240          txt="\n"+txt
241       return txt
242
243    def generPARAMETRE_EVAL(self,obj):
244       """
245          Cette methode convertit un PARAMETRE_EVAL
246          en une liste de chaines de caracteres a la syntaxe python
247       """
248       if obj.valeur == None:
249          return obj.nom + ' = None ;\n'
250       else:
251          return obj.nom + ' = '+ self.generator(obj.valeur) +';\n'
252
253    def generITEM_PARAMETRE(self,obj):
254        return repr(obj) 
255
256    def generFormula(self,obj):
257        #return repr(obj) 
258        return str(obj) 
259
260    def generPARAMETRE(self,obj):
261       """
262          Cette methode convertit un PARAMETRE
263          en une liste de chaines de caracteres a la syntaxe python
264       """
265       return repr(obj) + ";\n"
266
267    def generETAPE_NIVEAU(self,obj):
268       """
269          Cette methode convertit une etape niveau
270          en une liste de chaines de caracteres a la syntaxe python
271       """
272       l=[]
273       if obj.etapes_niveaux == []:
274         for etape in obj.etapes:
275           l.append(self.generator(etape))
276       else:
277         for etape_niveau in obj.etapes_niveaux:
278           l.extend(self.generator(etape_niveau))
279       return l
280
281    def generETAPE(self,obj):
282       """
283          Cette methode convertit une etape
284          en une liste de chaines de caracteres a la syntaxe python
285       """
286       try:
287         sdname= self.generator(obj.sd)
288         if  string.find(sdname,'SD_') != -1: sdname='sansnom'
289       except:
290         sdname='sansnom'
291       l=[]
292       label=sdname + '='+obj.definition.nom+'('
293       l.append(label)
294       if obj.reuse != None :
295         str = 'reuse ='+ self.generator(obj.reuse) + ','
296         l.append(str)
297       for v in obj.mc_liste:
298         if isinstance(v,Accas.MCBLOC) :
299           liste=self.generator(v)
300           for mocle in liste :
301             l.append(mocle)
302         elif isinstance(v,Accas.MCSIMP) :
303           text=self.generator(v)
304           l.append(v.nom+'='+text)
305         else:
306           # MCFACT ou MCList
307           liste=self.generator(v)
308           liste[0]=v.nom+'='+liste[0]
309           l.append(liste)
310       if len(l) == 1:
311         l[0]=label+');'
312       else :
313         l.append(');')
314       return l
315
316    def generFORM_ETAPE(self,obj):
317         """
318             Methode particuliere pour les objets de type FORMULE
319         """
320         l=[]
321         nom = obj.get_nom()
322         if nom == '' : nom = 'sansnom'
323         l.append(nom + ' = FORMULE(')
324         for v in obj.mc_liste:
325             text=self.generator(v)
326             l.append(v.nom+'='+text)
327         l.append(');')
328         return l
329
330    def generMACRO_ETAPE(self,obj):
331       """
332          Cette methode convertit une macro-etape
333          en une liste de chaines de caracteres a la syntaxe python
334       """
335       try:
336         if obj.sd == None:
337           sdname=''
338         else:
339           sdname= self.generator(obj.sd)+'='
340       except:
341         sdname='sansnom='
342       l=[]
343       label = sdname + obj.definition.nom+'('
344       l.append(label)
345       if obj.reuse != None:
346          # XXX faut il la virgule ou pas ????
347          str = "reuse =" + self.generator(obj.reuse) + ','
348          l.append(str)
349       for v in obj.mc_liste:
350         if isinstance(v,Accas.MCBLOC) :
351           liste=self.generator(v)
352           for mocle in liste :
353             l.append(mocle)
354         elif isinstance(v,Accas.MCSIMP) :
355           text=self.generator(v)
356           l.append(v.nom+'='+text)
357         else:
358           # MCFACT ou MCList
359           liste=self.generator(v)
360           liste[0]=v.nom+'='+liste[0]
361           l.append(liste)
362
363       if len(l) == 1:
364         l[0]=label+');'
365       else :
366         l.append(');')
367       return l
368
369    def generPROC_ETAPE(self,obj):
370       """
371          Cette methode convertit une PROC etape
372          en une liste de chaines de caracteres a la syntaxe python
373       """
374       l=[]
375       label=obj.definition.nom+'('
376       l.append(label)
377       for v in obj.mc_liste:
378         if isinstance(v,Accas.MCBLOC) :
379           liste=self.generator(v)
380           for mocle in liste :
381             l.append(mocle)
382         elif isinstance(v,Accas.MCSIMP) :
383           text=self.generator(v)
384           l.append(v.nom+'='+text)
385         else:
386           # MCFACT ou MCList
387           liste=self.generator(v)
388           liste[0]=v.nom+'='+liste[0]
389           l.append(liste)
390
391       if len(l) == 1:
392         l[0]=label+');'
393       else :
394         l.append(');')
395       return l
396
397    def generASSD(self,obj):
398       """
399           Convertit un objet derive d'ASSD en une chaine de caracteres a la
400           syntaxe python
401       """
402       return obj.get_name()
403
404    def generMCFACT(self,obj):
405       """
406           Convertit un objet MCFACT en une liste de chaines de caracteres a la
407           syntaxe python
408       """
409       l=[]
410       l.append('_F(')
411       for v in obj.mc_liste:
412          if not isinstance(v,Accas.MCSIMP) and not isinstance (v,Accas.MCBLOC) :
413            # on est en presence d'une entite composee : on recupere une liste
414            liste=self.generator(v)
415            liste[0]=v.nom+'='+liste[0]
416            l.append(liste)
417          elif isinstance(v,Accas.MCBLOC):
418            liste=self.generator(v)
419            for arg in liste :
420              l.append(arg)
421          else:
422            # on est en presence d'un MCSIMP : on recupere une string
423            text =self.generator(v)
424            l.append(v.nom+'='+text)
425       # il faut etre plus subtil dans l'ajout de la virgule en differenciant 
426       # le cas ou elle est obligatoire (si self a des freres cadets 
427       # dans self.parent) ou non
428       # (cas ou self est seul ou le benjamin de self.parent)
429       l.append('),')
430       return l
431
432    def generMCList(self,obj):
433       """
434           Convertit un objet MCList en une liste de chaines de caracteres a la
435           syntaxe python
436       """
437       if len(obj.data) > 1:
438          l=['(']
439          for mcfact in obj.data: l.append(self.generator(mcfact))
440          l.append('),')
441       else:
442          l= self.generator(obj.data[0])
443       return l
444
445    def generMCBLOC(self,obj):
446       """
447           Convertit un objet MCBLOC en une liste de chaines de caracteres a la
448           syntaxe python
449       """
450       l=[]
451       for v in obj.mc_liste:
452         if isinstance(v,Accas.MCBLOC) :
453           liste=self.generator(v)
454           for mocle in liste :
455             l.append(mocle)
456         elif isinstance(v,Accas.MCFACT):
457           liste=self.generator(v)
458         elif isinstance(v,Accas.MCList):
459           liste=self.generator(v)
460           liste[0]=v.nom+'='+liste[0]
461           # PN  essai de correction bug identation
462           if (hasattr(v,'data')) :
463             if (isinstance(v.data[0],Accas.MCFACT) and (len(v.data) == 1)):
464                l.append(liste)
465             else:
466                for mocle in liste :
467                  l.append(mocle)
468           else :
469              for mocle in liste :
470                l.append(mocle)
471         else:
472           data=self.generator(v)
473           if type(data) == types.ListType:
474             data[0]=v.nom+'='+data[0]
475           else:
476             data=v.nom+'='+data
477           l.append(data)
478       return l
479
480
481    def format_item(self,valeur,etape,obj):
482       if (type(valeur) == types.FloatType or 'R' in obj.definition.type) and not(isinstance(valeur,Accas.PARAMETRE)) :
483          # Pour un flottant on utilise str
484          # ou la notation scientifique
485          # On ajoute un . si il n y en a pas dans la valeur
486          s = str(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       #      print valeur
520       #      s = self.generator(valeur)
521
522       else :
523          # Pour les autres types on utilise repr
524          s = repr(valeur)
525       return s
526
527    def generMCSIMP(self,obj) :
528       """
529           Convertit un objet MCSIMP en une liste de chaines de caracteres a la
530           syntaxe python
531       """
532       waitTuple=0
533       if type(obj.valeur) in (types.TupleType,types.ListType) :
534          s = ''
535          for ss_type in obj.definition.type:
536           if repr(ss_type).find('Tuple') != -1 :
537              waitTuple=1
538              break
539
540          if waitTuple :
541             #s = str(obj.valeur) +','
542             #obj.valeurFormatee=obj.valeur
543             s = obj.GetText() +','
544             obj.valeurFormatee=obj.GetText()
545          else :
546             obj.valeurFormatee=[]
547             for val in obj.valeur :
548                s =s +self.format_item(val,obj.etape,obj) + ','
549                obj.valeurFormatee.append(self.format_item(val,obj.etape,obj))
550             if len(obj.valeur) > 1:
551                s = '(' + s + '),'
552             if obj.valeur==[] : s="(),"
553          if obj.nbrColonnes() :
554             s=self.formatColonnes(obj.nbrColonnes(),obj.valeur,obj)
555       else :
556          obj.valeurFormatee=obj.valeur
557          s=self.format_item(obj.valeur,obj.etape,obj) + ','
558       return s
559
560
561    def formatColonnes(self,nbrColonnes,listeValeurs,obj):
562       #try :
563       print listeValeurs
564       if 1 == 1 :
565         indice=0
566         textformat="("
567         while ( indice < len(listeValeurs) ) :
568           try :
569           #if 1 :
570             for l in range(nbrColonnes) :
571                 texteVariable=self.format_item(listeValeurs[indice],obj.etape,obj)
572                 textformat=textformat+texteVariable+" ,"
573                 indice=indice+1
574             textformat=textformat+"\n"
575           except :
576           #else :
577             while ( indice < len(listeValeurs) ) :
578                 texteVariable=self.format_item(listeValeurs[indice],obj.etape,obj)
579                 textformat=textformat+texteVariable+", "
580                 indice=indice+1
581             textformat=textformat+"\n"
582         textformat=textformat[0:-1]+"),\n"
583       #except :
584       else :
585          textformat=str(obj.valeur)
586       print textformat
587       return textformat