Salome HOME
PN Pour les formules
[tools/eficas.git] / Editeur / readercata.py
1 # -*- coding: utf-8 -*-
2 #            CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
18 #
19 #
20 # ======================================================================
21 """
22     Ce module sert à lire un catalogue et à construire
23     un objet CataItem pour Eficas.
24     Il s'appuie sur la classe READERCATA
25 """
26 # Modules Python
27 import time
28 import os,sys,py_compile
29 import traceback
30 import cPickle
31 import Pmw
32
33 # Modules Eficas
34 import prefs
35 import splash
36 import fontes
37 import analyse_catalogue
38 from Noyau.N_CR import CR
39 from widgets import showinfo,showerror
40 from widgets import Fenetre
41 from utils import init_rep_cata_dev
42
43 #import catabrowser
44 import autre_analyse_cata
45 import uiinfo
46
47 class READERCATA:
48
49    menu_defs=[
50               ('Catalogue',[
51                            ("Rapport de validation catalogue",'visuCRCATA'),
52                          ]
53               )
54              ]
55
56    button_defs=[]
57
58    def __init__(self,appli,parent):
59       self.appli=appli
60       self.parent=parent
61       self.code=self.appli.code
62       self.appli.format_fichier.set('python')
63       self.OpenCata()
64       self.cataitem=None
65
66    def OpenCata(self):
67       """ 
68           Ouvre le catalogue standard du code courant, cad le catalogue présent
69           dans le répertoire Cata 
70       """
71       message1 = "Compilation des fichiers Eficas \n\n Veuillez patienter ..."
72       if self.appli.test == 0 :
73          splash._splash.configure(text = message1)
74       self.configure_barre(4)
75       liste_cata_possibles=[]
76       for catalogue in self.appli.CONFIGURATION.catalogues:
77           if catalogue[0] == self.code :
78              liste_cata_possibles.append(catalogue)
79       if len(liste_cata_possibles)==1:
80           self.fic_cata = liste_cata_possibles[0][2]
81           self.code = self.appli.CONFIGURATION.catalogues[0][0]
82           self.version_code = liste_cata_possibles[0][1]
83           self.appli.format_fichier.set(liste_cata_possibles[0][3])
84       elif len(liste_cata_possibles)==0:
85           # aucun catalogue défini dans le fichier Accas/editeur.ini
86           if self.code == 'ASTER' :
87               self.fic_cata = os.path.join(prefs.CODE_PATH,'Cata','cata.py')
88           elif self.code == 'SATURNE' :
89               self.fic_cata = os.path.join(prefs.CODE_PATH,'Cata','cata_saturne.py')
90           elif self.code == 'DESCARTES':
91               self.fic_cata = os.path.join(prefs.CODE_PATH,'Cata','cata_descartes.py')
92           else :
93               print 'Code inconnu'
94               sys.exit(0)
95       else:
96           # plusieurs catalogues sont disponibles : il faut demander à l'utilisateur
97           # lequel il veut utiliser ...
98           self.ask_choix_catalogue()
99       if self.fic_cata == None :
100           self.parent.destroy()
101           sys.exit(0)
102       # détermination de fic_cata_c et fic_cata_p
103       self.fic_cata_c = self.fic_cata + 'c'
104       self.fic_cata_p = os.path.splitext(self.fic_cata)[0]+'_pickled.py'
105
106       if self.appli.test == 0 :
107          splash._splash.configure(text = "Debut compil cata: %d s" % time.clock())
108       # compilation éventuelle du catalogue
109       test = self.compile_cata(self.fic_cata,self.fic_cata_c)
110       self.update_barre()
111       if self.appli.test == 0 :
112          splash._splash.configure(text = "Fin compil cata: %d s" % time.clock())
113       if not test : showerror("Compilation catalogue","Impossible de compiler le catalogue %s" %self.fic_cata)
114
115       # import du catalogue
116       if self.appli.test == 0 :
117          splash._splash.configure(text = "Debut import_cata: %d s" % time.clock())
118       self.cata = self.import_cata(self.fic_cata)
119       self.update_barre()
120       if self.appli.test == 0 :
121          splash._splash.configure(text = "Fin import_cata: %d s" % time.clock())
122       if not self.cata : showerror("Import du catalogue","Impossible d'importer le catalogue %s" %self.fic_cata)
123
124       #
125       # analyse du catalogue (ordre des mots-clés)
126       #
127       if self.appli.test == 0 :
128          splash._splash.configure(text = "Debut Retrouve_Ordre: %d s" % time.clock())
129       # Retrouve_Ordre_Cata_Standard fait une analyse textuelle du catalogue
130       # remplacé par Retrouve_Ordre_Cata_Standard_autre qui utilise une numerotation
131       # des mots clés à la création
132       #self.Retrouve_Ordre_Cata_Standard()
133       self.Retrouve_Ordre_Cata_Standard_autre()
134       self.update_barre()
135       if self.appli.test == 0 :
136          splash._splash.configure(text = "Fin Retrouve_Ordre: %d s" % time.clock())
137       #
138       # analyse des données liées à l'IHM : UIinfo
139       #
140       uiinfo.traite_UIinfo(self.cata)
141       self.update_barre()
142
143       #
144       # traitement des clefs documentaires
145       #
146       self.traite_clefs_documentaires()
147
148       # chargement et analyse des catalogues développeur (le cas échéant)
149       #
150       if self.appli.CONFIGURATION.isdeveloppeur == 'OUI' :
151           init_rep_cata_dev(self.fic_cata,self.appli.CONFIGURATION.path_cata_dev)
152           fic_cata_dev = os.path.join(self.appli.CONFIGURATION.path_cata_dev,'cata_developpeur.py')
153           if os.path.isfile(fic_cata_dev):
154               # il y a bien un catalogue développeur : il faut récupérer le module_object associé ...
155               test = self.compile_cata(fic_cata_dev,fic_cata_dev+'c')
156               if not test :
157                   showinfo("Compilation catalogue développeur",
158                            "Erreur dans la compilation du catalogue développeur")
159                   self.cata = (self.cata,)
160               else:
161                   self.cata_dev =self.import_cata(fic_cata_dev)
162                   #self.Retrouve_Ordre_Cata_Developpeur()
163                   self.Retrouve_Ordre_Cata_Developpeur_autre()
164                   self.cata = (self.cata,self.cata_dev)
165           else:
166               self.cata = (self.cata,)
167       else:
168           self.cata = (self.cata,)
169
170    def import_cata(self,cata):
171       """ 
172           Réalise l'import du catalogue dont le chemin d'accès est donné par cata
173       """
174       import imp
175       if self.appli.test == 0 :
176          splash._splash.configure(text = "Chargement du catalogue")
177       nom_cata = os.path.splitext(os.path.basename(cata))[0]
178       rep_cata = os.path.dirname(cata)
179       sys.path[:0] = [rep_cata]
180       try :
181           f,p,d = imp.find_module(nom_cata)
182           o = imp.load_module(nom_cata,f,p,d)
183           return o
184       except Exception,e:
185           traceback.print_exc()
186           return 0
187
188    def Retrouve_Ordre_Cata_Standard_autre(self):
189       """ 
190           Construit une structure de données dans le catalogue qui permet
191           à EFICAS de retrouver l'ordre des mots-clés dans le texte du catalogue.
192           Pour chaque entité du catlogue on crée une liste de nom ordre_mc qui
193           contient le nom des mots clés dans le bon ordre
194       """ 
195       self.cata_ordonne_dico=autre_analyse_cata.analyse_catalogue(self.cata)
196
197    def Retrouve_Ordre_Cata_Standard(self):
198       """ 
199           Retrouve l'ordre des mots-clés dans le catalogue, cad :
200            - si ce dernier a été modifié, relance l'analyse du catalogue pour déterminer
201                l'ordre des mots-clés dans le catalogue
202            - s'il n'a pas été modifié, relie le fichier pickle 
203       """
204       time1 = os.path.getmtime(self.fic_cata)
205       try :
206           time2 = os.path.getmtime(self.fic_cata_p)
207       except:
208           time2 = 0
209       if time2 > time1 :
210           # l'objet catalogue n'a pas été modifié depuis le dernier "pickle"
211           self.Get_Ordre_Cata()
212       else :
213           # le catalogue a été modifié depuis le dernier "pickle" :
214           # il faut retrouver l'ordre du catalogue et refaire pickle
215           self.Get_Ordre_Cata(mode='cata')
216       self.appli.affiche_infos("Catalogue standard chargé")
217
218    def Retrouve_Ordre_Cata_Developpeur(self):
219       """ 
220           Retrouve l'ordre des mots-clés dans le catalogue, cad :
221           - si ce dernier a été modifié, relance l'analyse du catalogue pour déterminer
222             l'ordre des mots-clés dans le catalogue
223           - s'il n'a pas été modifié, relie le fichier pickle 
224       """
225       if self.code != 'ASTER' : return
226       fic_cata = os.path.join(self.appli.CONFIGURATION.path_cata_dev,'cata_developpeur.py')
227       message="Chargement catalogue développeur présent dans :\n %s..." % self.appli.CONFIGURATION.path_cata_dev
228       if self.appli.test == 0 :
229          splash._splash.configure(text = message,barre='oui')
230       cata_dev_ordonne = analyse_cata.analyse_catalogue(self,self.fic_cata)
231       self.cata_dev_ordonne_cr = cata_dev_ordonne.cr
232       cata_dev_ordonne_dico = cata_dev_ordonne.entites
233       self.cata_ordonne_dico.update(cata_dev_ordonne_dico)
234       self.appli.affiche_infos(" catalogue(s) développeur(s) chargé(s)" )
235
236    def Retrouve_Ordre_Cata_Developpeur_autre(self):
237       """
238           Retrouve l'ordre des mots-clés dans le catalogue, cad :
239           - si ce dernier a été modifié, relance l'analyse du catalogue pour déterminer
240             l'ordre des mots-clés dans le catalogue
241           - s'il n'a pas été modifié, relie le fichier pickle
242       """
243       if self.code != 'ASTER' : return
244       message="Chargement catalogue développeur présent dans :\n %s..." % self.appli.CONFIGURATION.path_cata_dev
245       if self.appli.test == 0 :
246          splash._splash.configure(text = message,barre='oui')
247       cata_dev_ordonne_dico = autre_analyse_cata.analyse_catalogue(self.cata_dev)
248       self.cata_ordonne_dico.update(cata_dev_ordonne_dico)
249       self.appli.affiche_infos(" catalogue(s) développeur(s) chargé(s)" )
250
251    def Get_Ordre_Cata(self,mode='pickle'):
252       """ 
253           Retrouve l'ordre du catalogue :
254             - mode='pickle ': tente de relire le fichier pickle et sinon lance l'analyse du catalogue
255             - mode='cata'   : force l'analyse du catalogue directement sans relire le pickle
256       """
257       if mode == 'pickle' :
258           try:
259               f = open(self.fic_cata_p)
260               u = cPickle.Unpickler(f)
261               if self.appli.test == 0 :
262                  splash._splash.configure(text = "Analyse du catalogue")
263               self.cata_ordonne_dico = u.load()
264               f.close()
265           except :
266               # on peut ne pas arriver à relire le fichier pickle s'il a été altéré
267               # ou (le plus probable) s'il a été créé sous un autre OS
268               self.Get_Ordre_Cata(mode='cata')
269       elif mode == 'cata':
270           if self.appli.test == 0 :
271               splash._splash.configure(text = "Analyse du catalogue",barre='oui')
272           cata_ordonne = analyse_catalogue.analyse_catalogue(self,self.fic_cata)
273           self.cata_ordonne_cr = cata_ordonne.cr
274           self.cata_ordonne_dico = cata_ordonne.entites
275           splash._splash.configure(text = "Sauvegarde des informations sur le catalogue")
276           f = open(self.fic_cata_p,'w+')
277           p = cPickle.Pickler(f)
278           p.dump(self.cata_ordonne_dico)
279           f.close()
280       else :
281           raise Exception("Appel à un mode inconnu de Get_Ordre_Cata : %s" % mode)
282           return
283
284    def ask_choix_catalogue(self):
285       """
286       Ouvre une fenêtre de sélection du catalogue dans le cas où plusieurs
287       ont été définis dans Accas/editeur.ini
288       """
289       # construction du dictionnaire et de la liste des catalogues
290       self.dico_catalogues = {}
291       defaut = None
292       for catalogue in self.appli.CONFIGURATION.catalogues:
293           if catalogue[0] == self.code :
294               self.dico_catalogues[catalogue[1]] = catalogue
295               if len(catalogue) == 5 :
296                   if catalogue[4]=='defaut' : defaut = catalogue[1]
297       liste_choix = self.dico_catalogues.keys()
298       liste_choix.sort()
299       # test si plusieurs catalogues ou non
300       if len(liste_choix) == 0:
301           showerror("Aucun catalogue déclaré pour %s" %self.code)
302           self.quit()
303       elif len(liste_choix) == 1:
304           self.fic_cata = self.dico_catalogues[liste_choix[0]][2]
305           self.version_code = liste_choix[0]
306           return
307       # création d'une boîte de dialogue modale
308       self.fenetre_choix_cata = Pmw.Dialog(splash._splash, #avec self.parent, ne marche pas sous Windows
309                                            buttons=('OK','ANNULER'),
310                                            defaultbutton = 'OK',
311                                            title = "Choix d'une version du code %s" %self.code,
312                                            command = self.chooseCata)
313       # construction des radioboutons
314       label = `len(liste_choix)`+' versions du code %s sont disponibles\n' %self.code
315       label = label + 'Veuillez choisir celle avec laquelle vous souhaitez travailler :'
316       self.radiobutton = Pmw.RadioSelect(self.fenetre_choix_cata.interior(),
317                                          buttontype='radiobutton',
318                                          labelpos = 'w',
319                                          label_text = label,
320                                          label_font = fontes.standard,
321                                          orient='vertical')
322       for choix in liste_choix :
323           self.radiobutton.add(choix)
324       if defaut == None :
325           # aucun catalogue par défaut n'a été spécifié dans Accas/editeur.ini
326           defaut = liste_choix[0]
327       self.radiobutton.invoke(defaut)
328       self.radiobutton.pack(fill='x',padx=10,pady=10)
329       # centrage de la fenêtre
330       self.fenetre_choix_cata.activate(geometry='centerscreenalways')
331
332    def chooseCata(self,txt):
333       """ 
334           Méthode activée lorsque l'utilisateur a fait son choix et cliqué sur 'OK' ou sur 'ANNULER'
335       """
336       if txt == 'OK' :
337           version_cata = self.radiobutton.getcurselection()
338           self.fic_cata = self.dico_catalogues[version_cata][2]
339           self.version_code = version_cata
340           self.appli.format_fichier.set(self.dico_catalogues[version_cata][3])
341           self.fenetre_choix_cata.destroy()
342       else:
343           self.parent.destroy()
344
345    def compile_cata(self,cata,catac):
346       """ 
347            Teste si le catalogue a bien besoin d'être recompilé et si oui, le compile et
348            affiche un message dans le splash . Retourne 1 si la compilation s'est bien déroulée,
349            0 sinon.
350       """
351       time1 = os.path.getmtime(cata)
352       try:
353           time2 = os.path.getmtime(catac)
354       except:
355           time2 = 0
356       if time1 > time2:
357           try:
358               # le catalogue doit être recompilé avant d'être importé
359               if self.appli.test == 0 :
360                  splash._splash.configure(text="Compilation du catalogue\nCela peut prendre plusieurs secondes ...")
361               py_compile.compile(cata)
362           except:
363               return 0
364       return 1
365
366
367 #--------------------------------------------------------------------------------
368 # Méthodes concernant la barre de progression lors de l'analyse du catalogue
369 #--------------------------------------------------------------------------------
370
371    def configure_barre(self,nbcommandes):
372       """ Configure la barre de progression en lui passant comme paramètre le
373           nombre de commandes du catalogue qui lui sert à déterminer la longueur de son incrément """
374       try:
375           if self.appli.test == 0 :
376              splash._splash.configure(barre='oui',ratio = nbcommandes)
377       except:
378           pass
379
380    def update_barre(self):
381       """ Update la position de la barre de progression : la fait progresser de son incrément """
382       try:
383           if self.appli.test == 0 :
384              splash._splash.update_barre()
385       except:
386           pass
387
388    def visuCRCATA(self):
389       """
390       Méthode permettant l'affichage du rapport de validation
391       """
392       cr = CR( debut = "Début rapport de validation du catalogue",
393                fin = "Fin rapport de validation du catalogue")
394       titre="rapport de validation du catalogue"
395       if hasattr(self,'cata_ordonne_cr') :
396           cr.add(self.cata_ordonne_cr)
397       if hasattr(self,'cata_dev_ordonne_cr') :
398           cr.add(self.cata_dev_ordonne_cr)
399       for cata in self.cata:
400           if hasattr(cata,'JdC'):
401               cr.add(cata.JdC.report())
402       texte_cr = str(cr)
403       self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
404
405
406    def traite_clefs_documentaires(self):
407       try:
408         self.fic_cata_clef=os.path.splitext(self.fic_cata_c)[0]+'_clefs_docu'
409         f=open(self.fic_cata_clef)
410       except:
411         #print "Pas de fichier associé contenant des clefs documentaires"
412         return
413
414       dict_clef_docu={}
415       for l in f.readlines():
416           clef=l.split(':')[0]
417           docu=l.split(':')[1]
418           docu=docu[0:-1]
419           dict_clef_docu[clef]=docu
420       for oper in self.cata.JdC.commandes:
421            if dict_clef_docu.has_key(oper.nom):
422               oper.docu=dict_clef_docu[oper.nom]