1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2017 EDF R&D
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.
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.
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
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 Ce module contient le plugin generateur de fichier au format
25 from __future__ import absolute_import
27 from builtins import str
28 from builtins import object
29 from builtins import range
35 from Noyau import N_CR
36 from Noyau.N_utils import repr_float
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
49 Retourne les informations necessaires pour le chargeur de plugins
51 Ces informations sont retournees dans un dictionnaire
56 # La factory pour creer une instance du plugin
57 'factory' : PythonGenerator,
61 class PythonGenerator(object):
63 Ce generateur parcourt un objet de type JDC et produit
64 un fichier au format python
66 L'acquisition et le parcours sont realises par la methode
67 generator.gener(objet_jdc,format)
69 L'ecriture du fichier au format ini par appel de la methode
70 generator.writefile(nom_fichier)
72 Ses caracteristiques principales sont exposees dans des attributs
74 - extensions : qui donne une liste d'extensions de fichier preconisees
77 # Les extensions de fichier preconisees
80 def __init__(self,cr=None):
81 # Si l'objet compte-rendu n'est pas fourni, on utilise le compte-rendu standard
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
91 def writefile(self,filename):
96 def gener(self,obj,format='brut',config=None,appliEficas=None):
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
106 print ('appel a gener avec None')
108 self.appliEficas=appliEficas
109 liste= self.generator(obj)
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()
120 self.text=jdc_formate.formateJdc()
122 #s = StringIO.StringIO()
123 #sortby = 'cumulative'
124 #ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
126 #print (s.getValue())
128 elif format == 'Ligne':
129 jdc_formate = FormatageLigne(liste,mode='.py')
130 self.text=jdc_formate.formateJdc()
132 raise EficasException(tr("Format non implemente ") +format)
135 def generator(self,obj):
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 !!!)
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)
183 raise EficasException(tr("Type d'objet non prevu") +obj)
185 def generJDC(self,obj):
187 Cette methode convertit un objet JDC en une liste de chaines de
188 caracteres a la syntaxe python
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))
202 for etape_niveau in obj.etapes_niveaux:
203 l.extend(self.generator(etape_niveau))
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:
212 def generUserASSD(self,obj):
213 classeName = obj.__class__.__name__
214 if obj.valeur == None :
215 texte = obj.nom + '=' + classeName + '()'
218 def generMCNUPLET(self,obj):
220 Methode generant une representation de self permettant son ecriture
221 dans le format python
225 for v in obj.mcListe:
226 text = re.sub(".*=","",self.generator(v))
231 def generCOMMANDE_COMM(self,obj):
233 Cette methode convertit un COMMANDE_COMM
234 en une liste de chaines de caracteres a la syntaxe python
236 l_lignes = obj.valeur.split('\n')
238 for ligne in l_lignes:
239 txt = txt + '##'+ligne+'\n'
242 def generEVAL(self,obj):
244 Cette methode convertit un EVAL
245 en une liste de chaines de caracteres a la syntaxe python
247 return 'EVAL("""'+ obj.valeur +'""")'
249 def generCOMMENTAIRE(self,obj):
251 Cette methode convertit un COMMENTAIRE
252 en une liste de chaines de caracteres a la syntaxe python
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
258 sans_saut = re.sub("\n$","",obj.valeur)
259 l_lignes = sans_saut.split('\n')
262 for ligne in l_lignes:
263 txt = txt + '#'+ligne+'\n'
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(" ?\#")
274 def generPARAMETRE_EVAL(self,obj):
276 Cette methode convertit un PARAMETRE_EVAL
277 en une liste de chaines de caracteres a la syntaxe python
279 if obj.valeur == None:
280 return obj.nom + ' = None ;\n'
282 return obj.nom + ' = '+ self.generator(obj.valeur) +';\n'
284 def generITEM_PARAMETRE(self,obj):
287 def generFormula(self,obj):
291 def generPARAMETRE(self,obj):
293 Cette methode convertit un PARAMETRE
294 en une liste de chaines de caracteres a la syntaxe python
296 return repr(obj) + ";\n"
298 def generETAPE_NIVEAU(self,obj):
300 Cette methode convertit une etape niveau
301 en une liste de chaines de caracteres a la syntaxe python
304 if obj.etapes_niveaux == []:
305 for etape in obj.etapes:
306 l.append(self.generator(etape))
308 for etape_niveau in obj.etapes_niveaux:
309 l.extend(self.generator(etape_niveau))
312 def generETAPE(self,obj):
314 Cette methode convertit une etape
315 en une liste de chaines de caracteres a la syntaxe python
318 sdname= self.generator(obj.sd)
319 if sdname.find('SD_') != -1: sdname='sansnom'
323 label=sdname + '='+obj.definition.nom+'('
325 if obj.reuse != None :
326 str = 'reuse ='+ self.generator(obj.reuse) + ','
328 for v in obj.mcListe:
329 if isinstance(v,Accas.MCBLOC) :
330 liste=self.generator(v)
333 elif isinstance(v,Accas.MCSIMP) :
334 text=self.generator(v)
335 l.append(v.nom+'='+text)
338 liste=self.generator(v)
339 liste[0]=v.nom+'='+liste[0]
347 def generFORM_ETAPE(self,obj):
349 Methode particuliere pour les objets de type FORMULE
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)
361 def generMACRO_ETAPE(self,obj):
363 Cette methode convertit une macro-etape
364 en une liste de chaines de caracteres a la syntaxe python
370 sdname= self.generator(obj.sd)+'='
371 if sdname.find('SD_') != -1: sdname=''
375 label = sdname + obj.definition.nom+'('
377 if obj.reuse != None:
378 # XXX faut il la virgule ou pas ????
379 str = "reuse =" + self.generator(obj.reuse) + ','
381 for v in obj.mcListe:
382 if isinstance(v,Accas.MCBLOC) :
383 liste=self.generator(v)
386 elif isinstance(v,Accas.MCSIMP) :
387 text=self.generator(v)
388 l.append(v.nom+'='+text)
391 liste=self.generator(v)
392 liste[0]=v.nom+'='+liste[0]
401 def generPROC_ETAPE(self,obj):
403 Cette methode convertit une PROC etape
404 en une liste de chaines de caracteres a la syntaxe python
407 label=obj.definition.nom+'('
409 for v in obj.mcListe:
410 if isinstance(v,Accas.MCBLOC) :
411 liste=self.generator(v)
414 elif isinstance(v,Accas.MCSIMP) :
415 text=self.generator(v)
416 if text==None : text= ""
417 l.append(v.nom+'='+text)
420 liste=self.generator(v)
421 liste[0]=v.nom+'='+liste[0]
430 def generASSD(self,obj):
432 Convertit un objet derive d'ASSD en une chaine de caracteres a la
438 def generMCFACT(self,obj):
440 Convertit un objet MCFACT en une liste de chaines de caracteres a la
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]
451 elif isinstance(v,Accas.MCBLOC):
452 liste=self.generator(v)
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)
467 def generMCList(self,obj):
469 Convertit un objet MCList en une liste de chaines de caracteres a la
472 if len(obj.data) > 1:
474 for mcfact in obj.data: l.append(self.generator(mcfact))
477 l= self.generator(obj.data[0])
480 def generMCBLOC(self,obj):
482 Convertit un objet MCBLOC en une liste de chaines de caracteres a la
486 for v in obj.mcListe:
487 if isinstance(v,Accas.MCBLOC) :
488 liste=self.generator(v)
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)):
507 data=self.generator(v)
508 if data==None : data= ""
509 if type(data) == list:
510 data[0]=v.nom+'='+data[0]
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
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]
530 elif type(valeur) == bytes or type(valeur) == str :
531 if valeur.find('\n') == -1:
532 # pas de retour chariot, on utilise repr
534 elif valeur.find('"""') == -1:
535 # retour chariot mais pas de triple ", on formatte
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
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
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
559 # s = self.generator(valeur)
562 # Pour les autres types on utilise repr
566 def generMCSIMP(self,obj) :
568 Convertit un objet MCSIMP en une liste de chaines de caracteres a la
572 if type(obj.valeur) in (tuple,list) :
574 for ss_type in obj.definition.type:
575 if repr(ss_type).find('Tuple') != -1 :
580 #s = str(obj.valeur) +','
581 #obj.valeurFormatee=obj.valeur
582 s = obj.getText() +','
583 obj.valeurFormatee=obj.getText()
585 obj.valeurFormatee=[]
586 for val in obj.valeur :
587 s =s +self.formatItem(val,obj.etape,obj,1) + ','
589 obj.valeurFormatee.append(val)
591 obj.valeurFormatee.append(self.formatItem(val,obj.etape,obj))
592 if len(obj.valeur) >= 1:
594 if obj.valeur==[] or obj.valeur==() : s="(),"
595 if obj.nbrColonnes() :
596 s=self.formatColonnes(obj.nbrColonnes(),obj.valeur,obj)
598 obj.valeurFormatee=obj.valeur
599 s=self.formatItem(obj.valeur,obj.etape,obj) + ','
603 def formatColonnes(self,nbrColonnes,listeValeurs,obj):
608 while ( indice < len(listeValeurs) ) :
611 for l in range(nbrColonnes) :
612 texteVariable=self.formatItem(listeValeurs[indice],obj.etape,obj)
613 textformat=textformat+texteVariable+" ,"
615 textformat=textformat+"\n"
618 while ( indice < len(listeValeurs) ) :
619 texteVariable=self.formatItem(listeValeurs[indice],obj.etape,obj)
620 textformat=textformat+texteVariable+", "
622 textformat=textformat+"\n"
623 textformat=textformat[0:-1]+"),\n"
626 textformat=str(obj.valeur)