Salome HOME
834ee4100e0689608228e81b811f81395400e767
[tools/eficas.git] / Editeur / session.py
1 # -*- coding: iso-8859-15 -*-
2 """
3 Ce module centralise les informations issues de la ligne de commande.
4
5 La ligne de commande est parsee avec l'aide du module python optparse.
6 Les options possibles sont : -c, -j, -p, -d, -i, -f comme definies ci-dessous.
7
8 Un exemple typique d'utilisation est :
9 >>> ./appli.py -c V7.3 -d 1 -j aa -i 11 iii -p ppp -i 22 ii -j bb -f ff
10
11 qui demande a l'application d'ouvrir trois jeux de commandes.
12
13 Le premier (aa) a un include (11,iii) et est la suite du fichier poursuite ppp 
14 qui a lui meme un include (22,ii).
15
16 Le deuxieme bb est un jeu de commandes simple.
17
18 Le troisieme est decrit dans le fichier ff de type .ini
19 qui est parse par le module ConfigParser.
20 Chaque section du fichier decrit un jeu de commandes.
21 Un include est specifie par: numero logique=nom du fichier
22 Une poursuite est specifiee par: poursuite=reference a un jeu de commande 
23 Cette reference correspond a un nom de section decrivant le jeu de commandes.
24 Le jeu de commandes maitre est donne par l'entree globale jdc dans la section jdc.
25
26 Exemple:
27 [jdc]
28 jdc=a
29 [a]
30 comm=aa
31 poursuite=pours
32 11=iii
33 [pours]
34 comm=ppp
35 22=ii
36
37 La session utilisera le catalogue V7.3 en mode debug.
38 """
39
40 try:
41    import optparse
42    from optparse import OptionValueError
43 except:
44    from Tools import optparse
45    from Tools.optparse import OptionValueError
46
47 import os,traceback
48 import ConfigParser
49
50 # Les valeurs decodees par optparse sont mises dans un objet dictionnaire-like.
51 # On l'utilise comme environnement de session.
52 d_env={}
53 #
54 # L'attribut "studies" de d_env est une liste dans laquelle on range les etudes de niveau global.
55 # Une étude est stockée dans un dictionnaire.
56 # La clé "comm" du dictionnaire donne le nom du fichier de commandes principal
57 # La clé (optionnelle) "pours" du dictionnaire donne les informations pour une poursuite
58 # La valeur associée à la clé est un dictionnaire qui contient les informations sur
59 # le nom du fichier de commandes de la poursuite (clé "comm"), une éventuelle poursuite
60 # (clé "pours") et les includes (clés entières associées à des noms de fichier).
61 #
62 #
63 #
64 # Les informations (dictionnaire) associées au fichier de commandes en cours de traitement 
65 # sont stockées dans parser.values.current
66 # En general, il faut utiliser current et pas parser.values.studies car les informations
67 # sont stockées hiérarchiquement
68 #
69
70 def check_comm(option, opt_str, value, parser):
71     if not hasattr(parser.values,"studies"):
72        parser.values.studies=[]
73        parser.values.comm=[]
74     if not os.path.isfile(value):
75        raise OptionValueError("le fichier de commandes %s n'existe pas" % value)
76     parser.values.comm.append(value)
77     d_study={"comm":value}
78     parser.values.current=d_study
79     parser.values.studies.append(d_study)
80
81 def check_poursuite(option, opt_str, value, parser):
82     if parser.values.comm is None:
83        raise OptionValueError("un fichier de commandes doit etre defini avant une poursuite %s" % value)
84     if not os.path.isfile(value):
85        raise OptionValueError("le fichier poursuite %s n'existe pas" % value)
86     #current : fichier de commandes en cours de traitement (dictionnaire des infos)
87     comm=parser.values.current
88     d_study={"comm":value}
89     comm["pours"]=d_study
90     parser.values.current=d_study
91
92 def check_include(option, opt_str, value, parser):
93     try:
94        args=[int(parser.rargs[0]),parser.rargs[1]]
95     except:
96        raise OptionValueError("include mal defini %s" % parser.rargs[0:2])
97
98     del parser.rargs[0]
99     del parser.rargs[0]
100
101     if parser.values.comm is None:
102        raise OptionValueError("un fichier de commandes doit etre defini avant un include %s" % args)
103     if not os.path.isfile(args[1]):
104        raise OptionValueError("le fichier include %s n'existe pas" % args[1])
105
106     comm=parser.values.current
107     comm[args[0]]=args[1]
108
109
110 def check_jdc(config,jdc,parser,fich):
111     """
112         Fonction : analyse une section de fichier .ini pour en extraire
113                    les informations sur les fichiers poursuite et includes
114                    définis dans cette section
115
116         parser : objet analyseur de la ligne de commande
117         fich : nom du fichier .ini en cours d'analyse
118         config : objet de la classe ConfigParser permettant de parser le fichier fich
119         jdc : nom de la section du fichier fich à analyser
120     """
121     d_study={}
122
123     for o in config.options(jdc):
124        if o == "poursuite":
125           p=config.get(jdc,"poursuite")
126
127           if not config.has_option(p,"comm"):
128              raise OptionValueError("jdc %s manque fichier comm dans section %s" % (fich,p))
129           comm=config.get(p,"comm")
130           if not os.path.isfile(comm):
131              raise OptionValueError("jdc %s, le fichier de commandes %s n'existe pas" % (fich,comm))
132
133           pours=check_jdc(config,p,parser,fich)
134           pours["comm"]=comm
135           d_study["pours"]=pours
136           continue
137
138        try:
139           unit=int(o)
140           # si le parametre est un entier, il s'agit d'un include
141           inc=config.get(jdc,o)
142        except:
143           continue
144        if not os.path.isfile(inc):
145           raise OptionValueError("jdc %s fichier include %s, %s n'existe pas" % (fich,unit,inc))
146        d_study[unit]=inc
147
148     return d_study
149
150 def check_fich(option, opt_str, fich, parser):
151     """
152         Fonction : parse le fichier fich (format .ini)
153         
154         option : option en cours de traitement
155         opt_str : chaine de caracteres utilisee par l'utilisateur
156         fich : nom du fichier .ini donné par l'utilisateur
157         parser : objet parseur des options de la ligne de commande
158     """
159     if not os.path.isfile(fich):
160        raise OptionValueError("le fichier jdc %s n'existe pas" % fich)
161     if parser.values.fich is None:
162        parser.values.fich=[]
163     parser.values.fich.append(fich)
164     if not hasattr(parser.values,"studies"):
165        parser.values.studies=[]
166        parser.values.comm=[]
167     config = ConfigParser.ConfigParser()
168     config.read([fich])
169     if not config.has_option("jdc","jdc"):
170        raise OptionValueError("jdc %s manque option jdc dans section jdc")
171     jdc=config.get("jdc","jdc")
172
173     if not config.has_option(jdc,"comm"):
174        raise OptionValueError("jdc %s manque fichier comm dans section %s" % (fich,jdc))
175     comm=config.get(jdc,"comm")
176     if not os.path.isfile(comm):
177        raise OptionValueError("jdc %s, le fichier de commandes %s n'existe pas" % (fich,comm))
178     parser.values.comm.append(comm)
179
180     d_study=check_jdc(config,jdc,parser,fich)
181     d_study["comm"]=comm
182     parser.values.studies.append(d_study)
183
184 def print_pours(d_pours,dec=''):
185     # Les fichiers includes d'abord
186     for k,v in d_pours.items():
187        if k in ("pours","comm"):continue
188        print dec+" include",k," :",v
189
190     if d_pours.has_key("pours"):
191        # Description de la poursuite
192        print dec+" fichier poursuite:",d_pours["pours"]["comm"]
193        print_pours(d_pours["pours"],dec=dec+"++")
194
195 def print_d_env():
196     #print d_env
197     if d_env.studies is None:return
198     for study in d_env.studies:
199        print "nom etude:",study["comm"]
200        print_pours(study,dec="++")
201        print
202
203 def create_parser():
204     # creation du parser des options de la ligne de commande
205     parser=optparse.OptionParser(usage="usage: %prog [options]",version="%prog 1.8")
206
207     parser.add_option("-j","--jdc",dest="comm",type='string',
208                     action="callback",callback=check_comm,
209                     help="nom du fichier de commandes")
210     parser.add_option("-p","--poursuite", type="string",dest="pours",
211                   action="callback", callback=check_poursuite,
212                   help="nom du fichier poursuite")
213     parser.add_option("-i","--include", 
214                   action="callback", callback=check_include,
215                   nargs=2, help="numero d'unite suivi du nom du fichier include")
216
217     parser.add_option("-f","--fich", type="string",dest="fich",
218                   action="callback", callback=check_fich,
219                   help="fichier decrivant une etude")
220
221     parser.add_option("-c","--cata", action="store", type="string",dest="cata",
222                   help="version de catalogue a utiliser")
223
224     parser.add_option("-d","--debug", action="store", type="int",dest="debug",
225                   help="niveau de debug")
226
227     return parser
228
229 def parse(args):
230     parser=create_parser()
231     (options,args)=parser.parse_args(args[1:])
232     if not hasattr(options,"studies"):
233        options.studies=[]
234        options.comm=[]
235     try:
236        del parser.values.current
237     except:
238        pass
239
240     for file in args:
241          if os.path.isfile(file):
242             options.comm.append(file)
243             options.studies.append({"comm":file})
244          else:
245             parser.error("incorrect number of arguments")
246
247     global d_env
248     d_env=options
249     #print_d_env()
250     return options
251
252 def get_unit(d_study,appli):
253     """
254        Fonction : construit et retourne un dictionnaire contenant les informations
255                   sur les fichiers poursuite et includes sous la forme adaptée
256                   pour EFICAS
257                   [None : nom_fichier, texte_source, unites_associees,           # poursuite
258                    numero_include : nom_fichier, texte_source, unites_associees, # include
259                     ...] 
260        d_study : dictionnaire de l'etude
261        appli : objet application EFICAS (permet d'acceder aux services comme get_source)
262     """
263     return get_dunit(d_study,appli)
264
265 def get_dunit(d_unit,appli):
266     d={}
267     if d_unit.has_key("pours"):
268        # on a une poursuite
269        comm=d_unit["pours"]["comm"]
270        g=get_dunit(d_unit["pours"],appli)
271        text=appli.get_source(comm)
272        d[None]=comm,text,g
273
274     for k,v in d_unit.items():
275        if k in ("pours","comm"): continue
276        text=appli.get_source(v)
277        d[k]=v,text,d
278
279     return d