Salome HOME
except and print
[tools/eficas.git] / Editeur / session.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 centralise les informations issues de la ligne de commande.
22
23 La ligne de commande est parsee avec l'aide du module python optparse.
24 Les options possibles sont : -c, -j, -p, -d, -i, -f comme definies ci-dessous.
25
26 Un exemple typique d'utilisation est :
27 >>> ./appli.py -c V7.3 -d 1 -j aa -i 11 iii -p ppp -i 22 ii -j bb -f ff
28
29 qui demande a l'application d'ouvrir trois jeux de commandes.
30
31 Le premier (aa) a un include (11,iii) et est la suite du fichier poursuite ppp 
32 qui a lui meme un include (22,ii).
33
34 Le deuxieme bb est un jeu de commandes simple.
35
36 Le troisieme est decrit dans le fichier ff de type .ini
37 qui est parse par le module ConfigParser.
38 Chaque section du fichier decrit un jeu de commandes.
39 Un include est specifie par: numero logique=nom du fichier
40 Une poursuite est specifiee par: poursuite=reference a un jeu de commande 
41 Cette reference correspond a un nom de section decrivant le jeu de commandes.
42 Le jeu de commandes maitre est donne par l'entree globale jdc dans la section jdc.
43
44 Exemple:
45 [jdc]
46 jdc=a
47 [a]
48 comm=aa
49 poursuite=pours
50 11=iii
51 [pours]
52 comm=ppp
53 22=ii
54
55 La session utilisera le catalogue V7.3 en mode debug.
56 """
57
58 try:
59    import optparse
60    from optparse import OptionValueError
61 except:
62    from Tools import optparse
63    from Tools.optparse import OptionValueError
64
65 import os,traceback
66 import ConfigParser
67 import re
68
69 from Extensions.i18n import tr
70
71 # Les valeurs decodees par optparse sont mises dans un objet dictionnaire-like.
72 # On l'utilise comme environnement de session.
73 d_env={}
74 #
75 # L'attribut "studies" de d_env est une liste dans laquelle on range les etudes de niveau global.
76 # Une etude est stockee dans un dictionnaire.
77 # La cle "comm" du dictionnaire donne le nom du fichier de commandes principal
78 # La cle (optionnelle) "pours" du dictionnaire donne les informations pour une poursuite
79 # La valeur associee a la cle est un dictionnaire qui contient les informations sur
80 # le nom du fichier de commandes de la poursuite (cle "comm"), une eventuelle poursuite
81 # (cle "pours") et les includes (cles entieres associees a des noms de fichier).
82 #
83 #
84 #
85 # Les informations (dictionnaire) associees au fichier de commandes en cours de traitement 
86 # sont stockees dans parser.values.current
87 # En general, il faut utiliser current et pas parser.values.studies car les informations
88 # sont stockees hierarchiquement
89 #
90
91 def check_comm(option, opt_str, value, parser):
92     if not hasattr(parser.values,"studies"):
93        parser.values.studies=[]
94        parser.values.comm=[]
95     if not os.path.isfile(value):
96        raise OptionValueError(tr("le fichier de commandes %s n'existe pas", value))
97     parser.values.comm.append(value)
98     d_study={"comm":value}
99     parser.values.current=d_study
100     parser.values.studies.append(d_study)
101
102 def check_poursuite(option, opt_str, value, parser):
103     if parser.values.comm is None:
104        raise OptionValueError(tr("un fichier de commandes doit etre defini avant une poursuite %s", value))
105     if not os.path.isfile(value):
106        raise OptionValueError(tr("le fichier poursuite %s n'existe pas", value))
107     #current : fichier de commandes en cours de traitement (dictionnaire des infos)
108     comm=parser.values.current
109     d_study={"comm":value}
110     comm["pours"]=d_study
111     parser.values.current=d_study
112
113 def check_include(option, opt_str, value, parser):
114     try:
115        args=[int(parser.rargs[0]),parser.rargs[1]]
116     except:
117        raise OptionValueError(tr("include mal defini %s", parser.rargs[0:2]))
118
119     del parser.rargs[0]
120     del parser.rargs[0]
121
122     if parser.values.comm is None:
123        raise OptionValueError(tr("un fichier de commandes doit etre defini avant un include %s", args))
124     if not os.path.isfile(args[1]):
125        raise OptionValueError(tr("le fichier include %s n'existe pas", args[1]))
126
127     comm=parser.values.current
128     comm[args[0]]=args[1]
129
130
131 def check_jdc(config,jdc,parser,fich):
132     """
133         Fonction : analyse une section de fichier .ini pour en extraire
134         les informations sur les fichiers poursuite et includes
135         definis dans cette section
136
137         parser : objet analyseur de la ligne de commande
138         fich : nom du fichier .ini en cours d'analyse
139         config : objet de la classe ConfigParser permettant de parser le fichier fich
140         jdc : nom de la section du fichier fich à analyser
141     """
142     d_study={}
143
144     for o in config.options(jdc):
145        if o == "poursuite":
146           p=config.get(jdc,"poursuite")
147
148           if not config.has_option(p,"comm"):
149              raise OptionValueError(tr(" jdc %(v_1)s manque \
150                                       fichier comm dans section %(v_2)s", \
151                                       {'v_1': fich, 'v_2': p}))
152           comm=config.get(p,"comm")
153           if not os.path.isfile(comm):
154              raise OptionValueError(tr("jdc %(v_1)s, le fichier\
155                                       de commandes %(v_2)s n'existe pas", \
156                                       {'v_1': fich, 'v_2': comm}))
157
158           pours=check_jdc(config,p,parser,fich)
159           pours["comm"]=comm
160           d_study["pours"]=pours
161           continue
162
163        try:
164           unit=int(o)
165           # si le parametre est un entier, il s'agit d'un include
166           inc=config.get(jdc,o)
167        except EficasException:
168           continue
169        if not os.path.isfile(inc):
170           raise OptionValueError(tr(" jdc %(v_1)s \
171                                    fichier include %(v_2)s, %(v_3)s \
172                                    n'existe pas", \
173                                    {'v_1': fich, 'v_2': unit, 'v_3': inc}))
174        d_study[unit]=inc
175
176     return d_study
177
178 def check_fich(option, opt_str, fich, parser):
179     """
180         Fonction : parse le fichier fich (format .ini)
181         
182         option : option en cours de traitement
183         opt_str : chaine de caracteres utilisee par l'utilisateur
184         fich : nom du fichier .ini donne par l'utilisateur
185         parser : objet parseur des options de la ligne de commande
186     """
187     if not os.path.isfile(fich):
188        raise OptionValueError(tr(" le fichier jdc %s n'existe pas", str(fich)))
189     if parser.values.fich is None:
190        parser.values.fich=[]
191     parser.values.fich.append(fich)
192     if not hasattr(parser.values,"studies"):
193        parser.values.studies=[]
194        parser.values.comm=[]
195     config = ConfigParser.ConfigParser()
196     config.read([fich])
197     if not config.has_option(u"jdc","jdc"):
198        raise OptionValueError(tr(" jdc %s manque option jdc dans section jdc", str(fich)))
199     jdc=config.get(u"jdc","jdc")
200
201     if not config.has_option(jdc,"comm"):
202        raise OptionValueError(tr(" jdc %(v_1)s manque fichier comm \
203                                 dans section %(v_2)s", {'v_1': fich, 'v_2': jdc}))
204     comm=config.get(jdc,"comm")
205     if not os.path.isfile(comm):
206        raise OptionValueError(tr("jdc %(v_1)s, le fichier de commandes \
207                                 %(v_2)s n'existe pas", {'v_1': fich, 'v_2': comm}))
208     parser.values.comm.append(comm)
209
210     d_study=check_jdc(config,jdc,parser,fich)
211     d_study["comm"]=comm
212     parser.values.studies.append(d_study)
213
214 def print_pours(d_pours,dec=''):
215     # Les fichiers includes d'abord
216     for k,v in d_pours.items():
217        if k in (u"pours","comm"):continue
218        print ( tr("%(v_1)s include %(v_2)s : %(v_3)s", {'v_1': str(dec), 'v_2': str(k), 'v_3': str(v)}))
219
220     if d_pours.has_key(u"pours"):
221        # Description de la poursuite
222        print (tr("%(v_1)s fichier poursuite: %(v_2)s", {'v_1': dec, 'v_2': d_pours["pours"]["comm"]}))
223        print_pours(d_pours["pours"],dec=dec+"++")
224
225 def print_d_env():
226     if d_env.studies is None:return
227     for study in d_env.studies:
228        print (tr("nom etude : %s", study["comm"]))
229        print_pours(study,dec="++")
230
231 def create_parser():
232     # creation du parser des options de la ligne de commande
233     #import prefs
234     parser=optparse.OptionParser(usage=tr("utilisation : %prog [options]"), version="%prog 1.13")
235
236     parser.add_option(u"-j","--jdc",dest="comm",type='string',
237                     action="callback",callback=check_comm,
238                     help=tr("nom du fichier de commandes"))
239
240     parser.add_option(u"-p","--poursuite", type="string",dest="pours",
241                   action="callback", callback=check_poursuite,
242                   help=tr("nom du fichier poursuite"))
243
244     parser.add_option(u"-i","--include", 
245                   action="callback", callback=check_include,
246                   nargs=2, help=tr("numero d'unite suivi du nom du fichier include"))
247
248     parser.add_option(u"-f","--fich", type="string",dest="fich",
249                   action="callback", callback=check_fich,
250                   help=tr("fichier decrivant une etude"))
251
252     parser.add_option(u"-c","--cata", action="store", type="string",dest="cata",
253                   help=tr("version de catalogue a utiliser"))
254
255     parser.add_option(u"-k","--kode", action="store", type="string",dest="code",
256                   help=tr("nom du code a utiliser"))
257
258     parser.add_option(u"-d","--debug", action="store", type="int",dest="debug",
259                   help=tr("niveau de debug"))
260
261     parser.add_option(u"-s","--schema", action="store", type="string",dest="ssCode",
262                   help=tr("schema"))
263     # To handle locale information
264     parser.add_option("-l", "--locale", action="store", type="string", dest="locale",
265                   help=tr("localisation de l'application, pour la traduction"))
266
267
268     return parser
269
270 def parse(args):
271     parser=create_parser()
272     (options,args)=parser.parse_args(args[1:])
273     if not hasattr(options,"studies"):
274        options.studies=[]
275        options.comm=[]
276     try:
277        del parser.values.current
278     except:
279        pass
280     for file in args:
281          if os.path.isfile(file):
282             options.comm.append(file)
283             options.studies.append({"comm":file})
284             #print options.studies
285          elif len(args)==1 and (re.search('.comm',file) or re.search('.map',file)):
286             try :
287                 f=open(file,'w')
288                 f.close()
289             except :
290                 parser.error(tr("Nombre incorrect d'arguments"))
291             options.comm.append(file)
292             options.studies.append({"comm":file})
293          elif len(args) == 1 and options.locale:
294             print (tr("Localisation specifiee pour l'application."))
295          else:
296             parser.error(tr("Nombre incorrect d'arguments"))
297
298     global d_env
299     d_env=options
300     #print_d_env()
301     return options
302
303 def get_unit(d_study,appli):
304     """
305        Fonction : construit et retourne un dictionnaire contenant les informations
306        sur les fichiers poursuite et includes sous la forme adaptee
307        pour EFICAS ::
308
309                   [None : nom_fichier, texte_source, unites_associees,           # poursuite
310                    numero_include : nom_fichier, texte_source, unites_associees, # include
311                     ...] 
312
313        d_study : dictionnaire de l'etude
314        appli : objet application EFICAS (permet d'acceder aux services comme get_source)
315     """
316     return get_dunit(d_study,appli)
317
318 def get_dunit(d_unit,appli):
319     d={}
320     if d_unit.has_key(u"pours"):
321        # on a une poursuite
322        comm=d_unit["pours"]["comm"]
323        g=get_dunit(d_unit["pours"],appli)
324        text=appli.get_source(comm)
325        d[None]=comm,text,g
326
327     for k,v in d_unit.items():
328        if k in (u"pours","comm"): continue
329        text=appli.get_source(v)
330        d[k]=v,text,d
331
332     return d