1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2021 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 : -l, -j, -p, -d, -i, -f comme definies ci-dessous.
26 Un exemple typique d'utilisation est :
27 >>> ./appli.py -v 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 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)
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
119 def checkInclude(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 checkJdc(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=checkJdc(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 checkFich(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=[]
204 config=ConfigParser.ConfigParser()
207 config=configparser.configparser()
209 if not config.has_option(u"jdc","jdc"):
210 raise OptionValueError(tr(" jdc %s manque option jdc dans section jdc", str(fich)))
211 jdc=config.get(u"jdc","jdc")
213 if not config.has_option(jdc,"comm"):
214 raise OptionValueError(tr(" jdc %(v_1)s manque fichier comm \
215 dans section %(v_2)s", {'v_1': fich, 'v_2': jdc}))
216 comm=config.get(jdc,"comm")
217 if not os.path.isfile(comm):
218 raise OptionValueError(tr("jdc %(v_1)s, le fichier de commandes \
219 %(v_2)s n'existe pas", {'v_1': fich, 'v_2': comm}))
220 parser.values.comm.append(comm)
222 d_study=checkJdc(config,jdc,parser,fich)
224 parser.values.studies.append(d_study)
226 def printPours(d_pours,dec=''):
227 # Les fichiers includes d'abord
228 for k,v in list(d_pours.items()):
229 if k in (u"pours","comm"):continue
230 print(( tr("%(v_1)s include %(v_2)s : %(v_3)s", {'v_1': str(dec), 'v_2': str(k), 'v_3': str(v)})))
232 if "pours" in d_pours:
233 # Description de la poursuite
234 print((tr("%(v_1)s fichier poursuite: %(v_2)s", {'v_1': dec, 'v_2': d_pours["pours"]["comm"]})))
235 printPours(d_pours["pours"],dec=dec+"++")
238 if d_env.studies is None:return
239 for study in d_env.studies:
240 print((tr("nom etude : %s", study["comm"])))
241 printPours(study,dec="++")
244 # creation du parser des options de la ligne de commande
246 parser=optparse.OptionParser(usage=tr("utilisation : %prog [options]"), version="%prog 9.5")
248 parser.add_option(u"-j","--jdc",dest="comm",type='string',
249 action="callback",callback=checkComm,
250 help=tr("nom du fichier de commandes"))
252 parser.add_option(u"-p","--poursuite", type="string",dest="pours",
253 action="callback", callback=checkPoursuite,
254 help=tr("nom du fichier poursuite"))
256 parser.add_option(u"-i","--include",
257 action="callback", callback=checkInclude,
258 nargs=2, help=tr("numero d'unite suivi du nom du fichier include"))
260 #parser.add_option(u"-f","--fich", type="string",dest="fich",
261 # action="callback", callback=checkFich,
262 # help=tr("fichier decrivant une etude"))
264 parser.add_option(u"-c","--cata", action="store", type="string",dest="fichierCata",
265 help=tr("catalogue a utiliser"))
267 parser.add_option(u"-v","--label", action="store", type="string",dest="labelCode",
268 help=tr("version de catalogue a utiliser"))
271 parser.add_option(u"-k","--kode", action="store", type="string",dest="code",
272 help=tr("nom du code a utiliser"))
274 parser.add_option(u"-d","--debug", action="store", type="int",dest="debug",
275 help=tr("niveau de debug"))
277 parser.add_option(u"-x","--withXSD", action="store_true", dest="withXSD",
279 help=tr("construit le .xml en meme temps que le .comm"))
281 parser.add_option(u"-a","--withEltAbstrait", action="store_true", dest="avecEltAbstrait",
283 help=tr("construit des elements abstraits dans le XSD pour gerer le cascading"))
285 parser.add_option(u"-s","--schema", action="store", type="string",dest="ssCode",
287 # To handle locale information
288 #parser.add_option("-l", "--locale", action="store", type="string", dest="locale",
289 # help=tr("localisation de l'application, pour la traduction"))
295 parser=createparser()
296 (options,args)=parser.parse_args(args[1:])
297 if not hasattr(options,"studies"):
300 if not hasattr(options,"fichierCata"): options.fichierCata=None
301 if not hasattr(options,"labelCode"): options.labelCode=None
304 except : print ('Please, source pyxb environment'); exit()
306 del parser.values.current
310 if os.path.isfile(file):
311 options.comm.append(file)
312 options.studies.append({"comm":file})
313 #print options.studies
314 elif len(args)==1 and (re.search('.comm',file) or re.search('.map',file) or re.search('.cas',file) or re.search('.xml',file)):
319 parser.error(tr("Nombre incorrect d'arguments"))
320 options.comm.append(file)
321 options.studies.append({"comm":file})
322 elif len(args) == 1 and options.locale:
323 print((tr("Localisation specifiee pour l'application.")))
325 parser.error(tr("Nombre incorrect d'arguments"))
333 def getUnit(d_study,appliEficas):
335 Fonction : construit et retourne un dictionnaire contenant les informations
336 sur les fichiers poursuite et includes sous la forme adaptee
339 [None : nom_fichier, texte_source, unites_associees, # poursuite
340 numero_include : nom_fichier, texte_source, unites_associees, # include
343 d_study : dictionnaire de l'etude
344 appliEficas : objet application EFICAS (permet d'acceder aux services comme getSource)
346 return getDunit(d_study,appliEficas)
348 def getDunit(d_unit,appliEficas):
350 if 'pours' in d_unit:
352 comm=d_unit["pours"]["comm"]
353 g=getDunit(d_unit["pours"],appliEficas)
354 text=appliEficas.getSource(comm)
357 for k,v in list(d_unit.items()):
358 if k in (u"pours","comm"): continue
359 text=appliEficas.getSource(v)