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