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