1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013 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,appli=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
105 self.appli=obj.get_jdc_root().appli
106 #self.appli=obj.appli
107 liste= self.generator(obj)
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()
118 self.text=jdc_formate.formate_jdc()
120 #s = StringIO.StringIO()
121 #sortby = 'cumulative'
122 #ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
124 #print (s.getvalue())
126 elif format == 'Ligne':
127 jdc_formate = FormatageLigne(liste,mode='.py')
128 self.text=jdc_formate.formate_jdc()
130 raise EficasException(tr("Format non implemente ") +format)
133 def generator(self,obj):
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 !!!)
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)
181 raise EficasException(tr("Type d'objet non prevu") +obj)
183 def generJDC(self,obj):
185 Cette methode convertit un objet JDC en une liste de chaines de
186 caracteres a la syntaxe python
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))
195 for etape_niveau in obj.etapes_niveaux:
196 l.extend(self.generator(etape_niveau))
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:
205 def generMCNUPLET(self,obj):
207 Methode generant une representation de self permettant son ecriture
208 dans le format python
212 for v in obj.mc_liste:
213 text = re.sub(".*=","",self.generator(v))
218 def generCOMMANDE_COMM(self,obj):
220 Cette methode convertit un COMMANDE_COMM
221 en une liste de chaines de caracteres a la syntaxe python
223 l_lignes = obj.valeur.split('\n')
225 for ligne in l_lignes:
226 txt = txt + '##'+ligne+'\n'
229 def generEVAL(self,obj):
231 Cette methode convertit un EVAL
232 en une liste de chaines de caracteres a la syntaxe python
234 return 'EVAL("""'+ obj.valeur +'""")'
236 def generCOMMENTAIRE(self,obj):
238 Cette methode convertit un COMMENTAIRE
239 en une liste de chaines de caracteres a la syntaxe python
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
245 sans_saut = re.sub("\n$","",obj.valeur)
246 l_lignes = sans_saut.split('\n')
249 for ligne in l_lignes:
250 txt = txt + '#'+ligne+'\n'
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(" ?\#")
261 def generPARAMETRE_EVAL(self,obj):
263 Cette methode convertit un PARAMETRE_EVAL
264 en une liste de chaines de caracteres a la syntaxe python
266 if obj.valeur == None:
267 return obj.nom + ' = None ;\n'
269 return obj.nom + ' = '+ self.generator(obj.valeur) +';\n'
271 def generITEM_PARAMETRE(self,obj):
274 def generFormula(self,obj):
278 def generPARAMETRE(self,obj):
280 Cette methode convertit un PARAMETRE
281 en une liste de chaines de caracteres a la syntaxe python
283 return repr(obj) + ";\n"
285 def generETAPE_NIVEAU(self,obj):
287 Cette methode convertit une etape niveau
288 en une liste de chaines de caracteres a la syntaxe python
291 if obj.etapes_niveaux == []:
292 for etape in obj.etapes:
293 l.append(self.generator(etape))
295 for etape_niveau in obj.etapes_niveaux:
296 l.extend(self.generator(etape_niveau))
299 def generETAPE(self,obj):
301 Cette methode convertit une etape
302 en une liste de chaines de caracteres a la syntaxe python
305 sdname= self.generator(obj.sd)
306 if sdname.find('SD_') != -1: sdname='sansnom'
310 label=sdname + '='+obj.definition.nom+'('
312 if obj.reuse != None :
313 str = 'reuse ='+ self.generator(obj.reuse) + ','
315 for v in obj.mc_liste:
316 if isinstance(v,Accas.MCBLOC) :
317 liste=self.generator(v)
320 elif isinstance(v,Accas.MCSIMP) :
321 text=self.generator(v)
322 l.append(v.nom+'='+text)
325 liste=self.generator(v)
326 liste[0]=v.nom+'='+liste[0]
334 def generFORM_ETAPE(self,obj):
336 Methode particuliere pour les objets de type FORMULE
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)
348 def generMACRO_ETAPE(self,obj):
350 Cette methode convertit une macro-etape
351 en une liste de chaines de caracteres a la syntaxe python
357 sdname= self.generator(obj.sd)+'='
361 label = sdname + obj.definition.nom+'('
363 if obj.reuse != None:
364 # XXX faut il la virgule ou pas ????
365 str = "reuse =" + self.generator(obj.reuse) + ','
367 for v in obj.mc_liste:
368 if isinstance(v,Accas.MCBLOC) :
369 liste=self.generator(v)
372 elif isinstance(v,Accas.MCSIMP) :
373 text=self.generator(v)
374 l.append(v.nom+'='+text)
377 liste=self.generator(v)
378 liste[0]=v.nom+'='+liste[0]
387 def generPROC_ETAPE(self,obj):
389 Cette methode convertit une PROC etape
390 en une liste de chaines de caracteres a la syntaxe python
393 label=obj.definition.nom+'('
395 for v in obj.mc_liste:
396 if isinstance(v,Accas.MCBLOC) :
397 liste=self.generator(v)
400 elif isinstance(v,Accas.MCSIMP) :
401 text=self.generator(v)
402 if text==None : text= ""
403 l.append(v.nom+'='+text)
406 liste=self.generator(v)
407 liste[0]=v.nom+'='+liste[0]
416 def generASSD(self,obj):
418 Convertit un objet derive d'ASSD en une chaine de caracteres a la
421 return obj.get_name()
423 def generMCFACT(self,obj):
425 Convertit un objet MCFACT en une liste de chaines de caracteres a la
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]
436 elif isinstance(v,Accas.MCBLOC):
437 liste=self.generator(v)
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)
452 def generMCList(self,obj):
454 Convertit un objet MCList en une liste de chaines de caracteres a la
457 if len(obj.data) > 1:
459 for mcfact in obj.data: l.append(self.generator(mcfact))
462 l= self.generator(obj.data[0])
465 def generMCBLOC(self,obj):
467 Convertit un objet MCBLOC en une liste de chaines de caracteres a la
471 for v in obj.mc_liste:
472 if isinstance(v,Accas.MCBLOC) :
473 liste=self.generator(v)
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)):
492 data=self.generator(v)
493 if data==None : data= ""
494 if type(data) == list:
495 data[0]=v.nom+'='+data[0]
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
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]
515 elif type(valeur) == bytes :
516 if valeur.find('\n') == -1:
517 # pas de retour chariot, on utilise repr
519 elif valeur.find('"""') == -1:
520 # retour chariot mais pas de triple ", on formatte
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
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
541 # s = self.generator(valeur)
544 # Pour les autres types on utilise repr
548 def generMCSIMP(self,obj) :
550 Convertit un objet MCSIMP en une liste de chaines de caracteres a la
554 if type(obj.valeur) in (tuple,list) :
556 for ss_type in obj.definition.type:
557 if repr(ss_type).find('Tuple') != -1 :
562 #s = str(obj.valeur) +','
563 #obj.valeurFormatee=obj.valeur
564 s = obj.GetText() +','
565 obj.valeurFormatee=obj.GetText()
567 obj.valeurFormatee=[]
568 for val in obj.valeur :
569 s =s +self.format_item(val,obj.etape,obj,1) + ','
571 obj.valeurFormatee.append(val)
573 obj.valeurFormatee.append(self.format_item(val,obj.etape,obj))
574 if len(obj.valeur) >= 1:
576 if obj.valeur==[] or obj.valeur==() : s="(),"
577 if obj.nbrColonnes() :
578 s=self.formatColonnes(obj.nbrColonnes(),obj.valeur,obj)
580 obj.valeurFormatee=obj.valeur
581 s=self.format_item(obj.valeur,obj.etape,obj) + ','
585 def formatColonnes(self,nbrColonnes,listeValeurs,obj):
590 while ( indice < len(listeValeurs) ) :
593 for l in range(nbrColonnes) :
594 texteVariable=self.format_item(listeValeurs[indice],obj.etape,obj)
595 textformat=textformat+texteVariable+" ,"
597 textformat=textformat+"\n"
600 while ( indice < len(listeValeurs) ) :
601 texteVariable=self.format_item(listeValeurs[indice],obj.etape,obj)
602 textformat=textformat+texteVariable+", "
604 textformat=textformat+"\n"
605 textformat=textformat[0:-1]+"),\n"
608 textformat=str(obj.valeur)