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