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