Salome HOME
e74df5de5e0aa8a615ef5b0b914d88ba6892fb0e
[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 re
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     #import prefs
207     parser=optparse.OptionParser(usage="usage: %prog [options]",version="%prog 1.13")
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")
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