]> SALOME platform Git repositories - tools/eficas.git/blob - Editeur/session.py
Salome HOME
ebbf40a90af40519782c008a60fb6631cbecadb9
[tools/eficas.git] / Editeur / session.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2017   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 from __future__ import absolute_import
59 from __future__ import print_function
60 try :
61   from builtins import str
62 except :
63   pass
64 try:
65    import optparse
66    from optparse import OptionValueError
67 except:
68    from Tools import optparse
69    from Tools.optparse import OptionValueError
70
71 import os,traceback
72 import six.moves.configparser
73 import re
74
75 from Extensions.i18n import tr
76
77 # Les valeurs decodees par optparse sont mises dans un objet dictionnaire-like.
78 # On l'utilise comme environnement de session.
79 d_env={}
80 #
81 # L'attribut "studies" de d_env est une liste dans laquelle on range les etudes de niveau global.
82 # Une etude est stockee dans un dictionnaire.
83 # La cle "comm" du dictionnaire donne le nom du fichier de commandes principal
84 # La cle (optionnelle) "pours" du dictionnaire donne les informations pour une poursuite
85 # La valeur associee a la cle est un dictionnaire qui contient les informations sur
86 # le nom du fichier de commandes de la poursuite (cle "comm"), une eventuelle poursuite
87 # (cle "pours") et les includes (cles entieres associees a des noms de fichier).
88 #
89 #
90 #
91 # Les informations (dictionnaire) associees au fichier de commandes en cours de traitement 
92 # sont stockees dans parser.values.current
93 # En general, il faut utiliser current et pas parser.values.studies car les informations
94 # sont stockees hierarchiquement
95 #
96
97 def checkComm(option, opt_str, value, parser):
98     if not hasattr(parser.values,"studies"):
99        parser.values.studies=[]
100        parser.values.comm=[]
101     if not os.path.isfile(value):
102        raise OptionValueError(tr("le fichier de commandes %s n'existe pas", value))
103     parser.values.comm.append(value)
104     d_study={"comm":value}
105     parser.values.current=d_study
106     parser.values.studies.append(d_study)
107
108 def checkPoursuite(option, opt_str, value, parser):
109     if parser.values.comm is None:
110        raise OptionValueError(tr("un fichier de commandes doit etre defini avant une poursuite %s", value))
111     if not os.path.isfile(value):
112        raise OptionValueError(tr("le fichier poursuite %s n'existe pas", value))
113     #current : fichier de commandes en cours de traitement (dictionnaire des infos)
114     comm=parser.values.current
115     d_study={"comm":value}
116     comm["pours"]=d_study
117     parser.values.current=d_study
118
119 def checkInclude(option, opt_str, value, parser):
120     try:
121        args=[int(parser.rargs[0]),parser.rargs[1]]
122     except:
123        raise OptionValueError(tr("include mal defini %s", parser.rargs[0:2]))
124
125     del parser.rargs[0]
126     del parser.rargs[0]
127
128     if parser.values.comm is None:
129        raise OptionValueError(tr("un fichier de commandes doit etre defini avant un include %s", args))
130     if not os.path.isfile(args[1]):
131        raise OptionValueError(tr("le fichier include %s n'existe pas", args[1]))
132
133     comm=parser.values.current
134     comm[args[0]]=args[1]
135
136
137 def checkJdc(config,jdc,parser,fich):
138     """
139         Fonction : analyse une section de fichier .ini pour en extraire
140         les informations sur les fichiers poursuite et includes
141         definis dans cette section
142
143         parser : objet analyseur de la ligne de commande
144         fich : nom du fichier .ini en cours d'analyse
145         config : objet de la classe Configparser permettant de parser le fichier fich
146         jdc : nom de la section du fichier fich a analyser
147     """
148     d_study={}
149
150     for o in config.options(jdc):
151        if o == "poursuite":
152           p=config.get(jdc,"poursuite")
153
154           if not config.has_option(p,"comm"):
155              raise OptionValueError(tr(" jdc %(v_1)s manque \
156                                       fichier comm dans section %(v_2)s", \
157                                       {'v_1': fich, 'v_2': p}))
158           comm=config.get(p,"comm")
159           if not os.path.isfile(comm):
160              raise OptionValueError(tr("jdc %(v_1)s, le fichier\
161                                       de commandes %(v_2)s n'existe pas", \
162                                       {'v_1': fich, 'v_2': comm}))
163
164           pours=checkJdc(config,p,parser,fich)
165           pours["comm"]=comm
166           d_study["pours"]=pours
167           continue
168
169        try:
170           unit=int(o)
171           # si le parametre est un entier, il s'agit d'un include
172           inc=config.get(jdc,o)
173        except EficasException:
174           continue
175        if not os.path.isfile(inc):
176           raise OptionValueError(tr(" jdc %(v_1)s \
177                                    fichier include %(v_2)s, %(v_3)s \
178                                    n'existe pas", \
179                                    {'v_1': fich, 'v_2': unit, 'v_3': inc}))
180        d_study[unit]=inc
181
182     return d_study
183
184 def checkFich(option, opt_str, fich, parser):
185     """
186         Fonction : parse le fichier fich (format .ini)
187         
188         option : option en cours de traitement
189         opt_str : chaine de caracteres utilisee par l'utilisateur
190         fich : nom du fichier .ini donne par l'utilisateur
191         parser : objet parseur des options de la ligne de commande
192     """
193     if not os.path.isfile(fich):
194        raise OptionValueError(tr(" le fichier jdc %s n'existe pas", str(fich)))
195     if parser.values.fich is None:
196        parser.values.fich=[]
197     parser.values.fich.append(fich)
198     if not hasattr(parser.values,"studies"):
199        parser.values.studies=[]
200        parser.values.comm=[]
201     config = six.moves.configparser.configparser()
202     config.read([fich])
203     if not config.has_option(u"jdc","jdc"):
204        raise OptionValueError(tr(" jdc %s manque option jdc dans section jdc", str(fich)))
205     jdc=config.get(u"jdc","jdc")
206
207     if not config.has_option(jdc,"comm"):
208        raise OptionValueError(tr(" jdc %(v_1)s manque fichier comm \
209                                 dans section %(v_2)s", {'v_1': fich, 'v_2': jdc}))
210     comm=config.get(jdc,"comm")
211     if not os.path.isfile(comm):
212        raise OptionValueError(tr("jdc %(v_1)s, le fichier de commandes \
213                                 %(v_2)s n'existe pas", {'v_1': fich, 'v_2': comm}))
214     parser.values.comm.append(comm)
215
216     d_study=checkJdc(config,jdc,parser,fich)
217     d_study["comm"]=comm
218     parser.values.studies.append(d_study)
219
220 def printPours(d_pours,dec=''):
221     # Les fichiers includes d'abord
222     for k,v in list(d_pours.items()):
223        if k in (u"pours","comm"):continue
224        print(( tr("%(v_1)s include %(v_2)s : %(v_3)s", {'v_1': str(dec), 'v_2': str(k), 'v_3': str(v)})))
225
226     if "pours" in d_pours:
227        # Description de la poursuite
228        print((tr("%(v_1)s fichier poursuite: %(v_2)s", {'v_1': dec, 'v_2': d_pours["pours"]["comm"]})))
229        printPours(d_pours["pours"],dec=dec+"++")
230
231 def printDEnv():
232     if d_env.studies is None:return
233     for study in d_env.studies:
234        print((tr("nom etude : %s", study["comm"])))
235        printPours(study,dec="++")
236
237 def createparser():
238     # creation du parser des options de la ligne de commande
239     #import prefs
240     parser=optparse.OptionParser(usage=tr("utilisation : %prog [options]"), version="%prog 1.13")
241
242     parser.add_option(u"-j","--jdc",dest="comm",type='string',
243                     action="callback",callback=checkComm,
244                     help=tr("nom du fichier de commandes"))
245
246     parser.add_option(u"-p","--poursuite", type="string",dest="pours",
247                   action="callback", callback=checkPoursuite,
248                   help=tr("nom du fichier poursuite"))
249
250     parser.add_option(u"-i","--include", 
251                   action="callback", callback=checkInclude,
252                   nargs=2, help=tr("numero d'unite suivi du nom du fichier include"))
253
254     parser.add_option(u"-f","--fich", type="string",dest="fich",
255                   action="callback", callback=checkFich,
256                   help=tr("fichier decrivant une etude"))
257
258     parser.add_option(u"-c","--cata", action="store", type="string",dest="cata",
259                   help=tr("version de catalogue a utiliser"))
260
261     parser.add_option(u"-v","--version_cata", action="store", type="string",dest="version_cata",
262                   help=tr("version de catalogue a utiliser"))
263
264
265     parser.add_option(u"-k","--kode", action="store", type="string",dest="code",
266                   help=tr("nom du code a utiliser"))
267
268     parser.add_option(u"-d","--debug", action="store", type="int",dest="debug",
269                   help=tr("niveau de debug"))
270
271     parser.add_option(u"-s","--schema", action="store", type="string",dest="ssCode",
272                   help=tr("schema"))
273     # To handle locale information
274     parser.add_option("-l", "--locale", action="store", type="string", dest="locale",
275                   help=tr("localisation de l'application, pour la traduction"))
276
277
278     return parser
279
280 def parse(args):
281     parser=createparser()
282     (options,args)=parser.parse_args(args[1:])
283     if not hasattr(options,"studies"):
284        options.studies=[]
285        options.comm=[]
286     try:
287        del parser.values.current
288     except:
289        pass
290     for file in args:
291          if os.path.isfile(file):
292             options.comm.append(file)
293             options.studies.append({"comm":file})
294             #print options.studies
295          elif len(args)==1 and (re.search('.comm',file) or re.search('.map',file) or re.search('.cas',file)):
296             try :
297                 f=open(file,'w')
298                 f.close()
299             except :
300                 parser.error(tr("Nombre incorrect d'arguments"))
301             options.comm.append(file)
302             options.studies.append({"comm":file})
303          elif len(args) == 1 and options.locale:
304             print((tr("Localisation specifiee pour l'application.")))
305          else:
306             parser.error(tr("Nombre incorrect d'arguments"))
307
308     global d_env
309     d_env=options
310     #printDEnv()
311     return options
312
313 def getUnit(d_study,appli):
314     """
315        Fonction : construit et retourne un dictionnaire contenant les informations
316        sur les fichiers poursuite et includes sous la forme adaptee
317        pour EFICAS ::
318
319                   [None : nom_fichier, texte_source, unites_associees,           # poursuite
320                    numero_include : nom_fichier, texte_source, unites_associees, # include
321                     ...] 
322
323        d_study : dictionnaire de l'etude
324        appli : objet application EFICAS (permet d'acceder aux services comme getSource)
325     """
326     return getDunit(d_study,appli)
327
328 def getDunit(d_unit,appli):
329     d={}
330     if 'pours' in d_unit:
331        # on a une poursuite
332        comm=d_unit["pours"]["comm"]
333        g=getDunit(d_unit["pours"],appli)
334        text=appli.getSource(comm)
335        d[None]=comm,text,g
336
337     for k,v in list(d_unit.items()):
338        if k in (u"pours","comm"): continue
339        text=appli.getSource(v)
340        d[k]=v,text,d
341
342     return d