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 centralise les informations issues de la ligne de commande.
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.
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
29 qui demande a l'application d'ouvrir trois jeux de commandes.
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).
34 Le deuxieme bb est un jeu de commandes simple.
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.
55 La session utilisera le catalogue V7.3 en mode debug.
58 from __future__ import absolute_import
59 from __future__ import print_function
61 from builtins import str
66 from optparse import OptionValueError
68 from Tools import optparse
69 from Tools.optparse import OptionValueError
72 import six.moves.configparser
75 from Extensions.i18n import tr
77 # Les valeurs decodees par optparse sont mises dans un objet dictionnaire-like.
78 # On l'utilise comme environnement de session.
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).
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
97 def check_comm(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)
108 def check_poursuite(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
119 def check_include(option, opt_str, value, parser):
121 args=[int(parser.rargs[0]),parser.rargs[1]]
123 raise OptionValueError(tr("include mal defini %s", parser.rargs[0:2]))
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]))
133 comm=parser.values.current
134 comm[args[0]]=args[1]
137 def check_jdc(config,jdc,parser,fich):
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
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
150 for o in config.options(jdc):
152 p=config.get(jdc,"poursuite")
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}))
164 pours=check_jdc(config,p,parser,fich)
166 d_study["pours"]=pours
171 # si le parametre est un entier, il s'agit d'un include
172 inc=config.get(jdc,o)
173 except EficasException:
175 if not os.path.isfile(inc):
176 raise OptionValueError(tr(" jdc %(v_1)s \
177 fichier include %(v_2)s, %(v_3)s \
179 {'v_1': fich, 'v_2': unit, 'v_3': inc}))
184 def check_fich(option, opt_str, fich, parser):
186 Fonction : parse le fichier fich (format .ini)
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
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()
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")
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)
216 d_study=check_jdc(config,jdc,parser,fich)
218 parser.values.studies.append(d_study)
220 def print_pours(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)})))
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 print_pours(d_pours["pours"],dec=dec+"++")
232 if d_env.studies is None:return
233 for study in d_env.studies:
234 print((tr("nom etude : %s", study["comm"])))
235 print_pours(study,dec="++")
238 # creation du parser des options de la ligne de commande
240 parser=optparse.OptionParser(usage=tr("utilisation : %prog [options]"), version="%prog 1.13")
242 parser.add_option(u"-j","--jdc",dest="comm",type='string',
243 action="callback",callback=check_comm,
244 help=tr("nom du fichier de commandes"))
246 parser.add_option(u"-p","--poursuite", type="string",dest="pours",
247 action="callback", callback=check_poursuite,
248 help=tr("nom du fichier poursuite"))
250 parser.add_option(u"-i","--include",
251 action="callback", callback=check_include,
252 nargs=2, help=tr("numero d'unite suivi du nom du fichier include"))
254 parser.add_option(u"-f","--fich", type="string",dest="fich",
255 action="callback", callback=check_fich,
256 help=tr("fichier decrivant une etude"))
258 parser.add_option(u"-c","--cata", action="store", type="string",dest="cata",
259 help=tr("version de catalogue a utiliser"))
261 parser.add_option(u"-k","--kode", action="store", type="string",dest="code",
262 help=tr("nom du code a utiliser"))
264 parser.add_option(u"-d","--debug", action="store", type="int",dest="debug",
265 help=tr("niveau de debug"))
267 parser.add_option(u"-s","--schema", action="store", type="string",dest="ssCode",
269 # To handle locale information
270 parser.add_option("-l", "--locale", action="store", type="string", dest="locale",
271 help=tr("localisation de l'application, pour la traduction"))
277 parser=create_parser()
278 (options,args)=parser.parse_args(args[1:])
279 if not hasattr(options,"studies"):
283 del parser.values.current
287 if os.path.isfile(file):
288 options.comm.append(file)
289 options.studies.append({"comm":file})
290 #print options.studies
291 elif len(args)==1 and (re.search('.comm',file) or re.search('.map',file)):
296 parser.error(tr("Nombre incorrect d'arguments"))
297 options.comm.append(file)
298 options.studies.append({"comm":file})
299 elif len(args) == 1 and options.locale:
300 print((tr("Localisation specifiee pour l'application.")))
302 parser.error(tr("Nombre incorrect d'arguments"))
309 def get_unit(d_study,appli):
311 Fonction : construit et retourne un dictionnaire contenant les informations
312 sur les fichiers poursuite et includes sous la forme adaptee
315 [None : nom_fichier, texte_source, unites_associees, # poursuite
316 numero_include : nom_fichier, texte_source, unites_associees, # include
319 d_study : dictionnaire de l'etude
320 appli : objet application EFICAS (permet d'acceder aux services comme get_source)
322 return get_dunit(d_study,appli)
324 def get_dunit(d_unit,appli):
326 if 'pours' in d_unit:
328 comm=d_unit["pours"]["comm"]
329 g=get_dunit(d_unit["pours"],appli)
330 text=appli.get_source(comm)
333 for k,v in list(d_unit.items()):
334 if k in (u"pours","comm"): continue
335 text=appli.get_source(v)