Salome HOME
421584a5a325dcc69569fcc5bb1edd2e2c6ec542
[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 import prefs
50 import re
51
52 # Les valeurs decodees par optparse sont mises dans un objet dictionnaire-like.
53 # On l'utilise comme environnement de session.
54 d_env={}
55 #
56 # L'attribut "studies" de d_env est une liste dans laquelle on range les etudes de niveau global.
57 # Une étude est stockée dans un dictionnaire.
58 # La clé "comm" du dictionnaire donne le nom du fichier de commandes principal
59 # La clé (optionnelle) "pours" du dictionnaire donne les informations pour une poursuite
60 # La valeur associée à la clé est un dictionnaire qui contient les informations sur
61 # le nom du fichier de commandes de la poursuite (clé "comm"), une éventuelle poursuite
62 # (clé "pours") et les includes (clés entières associées à des noms de fichier).
63 #
64 #
65 #
66 # Les informations (dictionnaire) associées au fichier de commandes en cours de traitement 
67 # sont stockées dans parser.values.current
68 # En general, il faut utiliser current et pas parser.values.studies car les informations
69 # sont stockées hiérarchiquement
70 #
71
72 def check_comm(option, opt_str, value, parser):
73     if not hasattr(parser.values,"studies"):
74        parser.values.studies=[]
75        parser.values.comm=[]
76     if not os.path.isfile(value):
77        raise OptionValueError("le fichier de commandes %s n'existe pas" % value)
78     parser.values.comm.append(value)
79     d_study={"comm":value}
80     parser.values.current=d_study
81     parser.values.studies.append(d_study)
82
83 def check_poursuite(option, opt_str, value, parser):
84     if parser.values.comm is None:
85        raise OptionValueError("un fichier de commandes doit etre defini avant une poursuite %s" % value)
86     if not os.path.isfile(value):
87        raise OptionValueError("le fichier poursuite %s n'existe pas" % value)
88     #current : fichier de commandes en cours de traitement (dictionnaire des infos)
89     comm=parser.values.current
90     d_study={"comm":value}
91     comm["pours"]=d_study
92     parser.values.current=d_study
93
94 def check_include(option, opt_str, value, parser):
95     try:
96        args=[int(parser.rargs[0]),parser.rargs[1]]
97     except:
98        raise OptionValueError("include mal defini %s" % parser.rargs[0:2])
99
100     del parser.rargs[0]
101     del parser.rargs[0]
102
103     if parser.values.comm is None:
104        raise OptionValueError("un fichier de commandes doit etre defini avant un include %s" % args)
105     if not os.path.isfile(args[1]):
106        raise OptionValueError("le fichier include %s n'existe pas" % args[1])
107
108     comm=parser.values.current
109     comm[args[0]]=args[1]
110
111
112 def check_jdc(config,jdc,parser,fich):
113     """
114         Fonction : analyse une section de fichier .ini pour en extraire
115         les informations sur les fichiers poursuite et includes
116         définis dans cette section
117
118         parser : objet analyseur de la ligne de commande
119         fich : nom du fichier .ini en cours d'analyse
120         config : objet de la classe ConfigParser permettant de parser le fichier fich
121         jdc : nom de la section du fichier fich à analyser
122     """
123     d_study={}
124
125     for o in config.options(jdc):
126        if o == "poursuite":
127           p=config.get(jdc,"poursuite")
128
129           if not config.has_option(p,"comm"):
130              raise OptionValueError("jdc %s manque fichier comm dans section %s" % (fich,p))
131           comm=config.get(p,"comm")
132           if not os.path.isfile(comm):
133              raise OptionValueError("jdc %s, le fichier de commandes %s n'existe pas" % (fich,comm))
134
135           pours=check_jdc(config,p,parser,fich)
136           pours["comm"]=comm
137           d_study["pours"]=pours
138           continue
139
140        try:
141           unit=int(o)
142           # si le parametre est un entier, il s'agit d'un include
143           inc=config.get(jdc,o)
144        except:
145           continue
146        if not os.path.isfile(inc):
147           raise OptionValueError("jdc %s fichier include %s, %s n'existe pas" % (fich,unit,inc))
148        d_study[unit]=inc
149
150     return d_study
151
152 def check_fich(option, opt_str, fich, parser):
153     """
154         Fonction : parse le fichier fich (format .ini)
155         
156         option : option en cours de traitement
157         opt_str : chaine de caracteres utilisee par l'utilisateur
158         fich : nom du fichier .ini donné par l'utilisateur
159         parser : objet parseur des options de la ligne de commande
160     """
161     if not os.path.isfile(fich):
162        raise OptionValueError("le fichier jdc %s n'existe pas" % fich)
163     if parser.values.fich is None:
164        parser.values.fich=[]
165     parser.values.fich.append(fich)
166     if not hasattr(parser.values,"studies"):
167        parser.values.studies=[]
168        parser.values.comm=[]
169     config = ConfigParser.ConfigParser()
170     config.read([fich])
171     if not config.has_option("jdc","jdc"):
172        raise OptionValueError("jdc %s manque option jdc dans section jdc")
173     jdc=config.get("jdc","jdc")
174
175     if not config.has_option(jdc,"comm"):
176        raise OptionValueError("jdc %s manque fichier comm dans section %s" % (fich,jdc))
177     comm=config.get(jdc,"comm")
178     if not os.path.isfile(comm):
179        raise OptionValueError("jdc %s, le fichier de commandes %s n'existe pas" % (fich,comm))
180     parser.values.comm.append(comm)
181
182     d_study=check_jdc(config,jdc,parser,fich)
183     d_study["comm"]=comm
184     parser.values.studies.append(d_study)
185
186 def print_pours(d_pours,dec=''):
187     # Les fichiers includes d'abord
188     for k,v in d_pours.items():
189        if k in ("pours","comm"):continue
190        print dec+" include",k," :",v
191
192     if d_pours.has_key("pours"):
193        # Description de la poursuite
194        print dec+" fichier poursuite:",d_pours["pours"]["comm"]
195        print_pours(d_pours["pours"],dec=dec+"++")
196
197 def print_d_env():
198     #print d_env
199     if d_env.studies is None:return
200     for study in d_env.studies:
201        print "nom etude:",study["comm"]
202        print_pours(study,dec="++")
203        print
204
205 def create_parser():
206     # creation du parser des options de la ligne de commande
207     parser=optparse.OptionParser(usage="usage: %prog [options]",version="%prog 1.9")
208
209     parser.add_option("-j","--jdc",dest="comm",type='string',
210                     action="callback",callback=check_comm,
211                     help="nom du fichier de commandes")
212
213     parser.add_option("-p","--poursuite", type="string",dest="pours",
214                   action="callback", callback=check_poursuite,
215                   help="nom du fichier poursuite")
216
217     parser.add_option("-i","--include", 
218                   action="callback", callback=check_include,
219                   nargs=2, help="numero d'unite suivi du nom du fichier include")
220
221     parser.add_option("-f","--fich", type="string",dest="fich",
222                   action="callback", callback=check_fich,
223                   help="fichier decrivant une etude")
224
225     parser.add_option("-c","--cata", action="store", type="string",dest="cata",
226                   help="version de catalogue a utiliser")
227
228     parser.add_option("-k","--kode", action="store", type="string",dest="code",
229                   help="nom du code a utiliser",default=prefs.code)
230
231     parser.add_option("-d","--debug", action="store", type="int",dest="debug",
232                   help="niveau de debug")
233
234     return parser
235
236 def parse(args):
237     parser=create_parser()
238     (options,args)=parser.parse_args(args[1:])
239     if not hasattr(options,"studies"):
240        options.studies=[]
241        options.comm=[]
242     try:
243        del parser.values.current
244     except:
245        pass
246
247     for file in args:
248          if os.path.isfile(file):
249             options.comm.append(file)
250             options.studies.append({"comm":file})
251          elif len(args)==1 and re.search('.comm',file):
252             try :
253                 f=open(file,'w')
254                 f.close()
255             except :
256                 parser.error("incorrect number of arguments")
257             options.comm.append(file)
258             options.studies.append({"comm":file})
259          else:
260             parser.error("incorrect number of arguments")
261
262     global d_env
263     d_env=options
264     #print_d_env()
265     return options
266
267 def get_unit(d_study,appli):
268     """
269        Fonction : construit et retourne un dictionnaire contenant les informations
270        sur les fichiers poursuite et includes sous la forme adaptée
271        pour EFICAS ::
272
273                   [None : nom_fichier, texte_source, unites_associees,           # poursuite
274                    numero_include : nom_fichier, texte_source, unites_associees, # include
275                     ...] 
276
277        d_study : dictionnaire de l'etude
278        appli : objet application EFICAS (permet d'acceder aux services comme get_source)
279     """
280     return get_dunit(d_study,appli)
281
282 def get_dunit(d_unit,appli):
283     d={}
284     if d_unit.has_key("pours"):
285        # on a une poursuite
286        comm=d_unit["pours"]["comm"]
287        g=get_dunit(d_unit["pours"],appli)
288        text=appli.get_source(comm)
289        d[None]=comm,text,g
290
291     for k,v in d_unit.items():
292        if k in ("pours","comm"): continue
293        text=appli.get_source(v)
294        d[k]=v,text,d
295
296     return d