]> git.llucax.com Git - software/sercom-old.git/blob - src/sc_suwi
Se agrega un timeout a sqlite para que espere si esta lockeada la DB.
[software/sercom-old.git] / src / sc_suwi
1 #!/usr/bin/env python2.4
2 # -*- encoding: iso-8859-1 -*-
3 # vim: set et sw=4 sts=4 :
4
5 # Módulos estándar
6 import os
7 import sys
8 import cgi
9 # Módulos externos
10 import sqlobject
11 # Módulos locales
12 import sercom
13 from sercom.sqlo import *
14
15 # Inicializo
16 conf, conn, log = sercom.init('cgi')
17
18 # Para debug web
19 import cgitb; cgitb.enable()
20
21 #XXX HORRIBLE
22 PASSWD = conf.get('general', 'cgipw')
23
24 def http_header_html(req):
25     return 'Content-type: text/html\r\n\r\n'
26
27 def http_header_zip(req, filename):
28     return 'Content-type: application/zip\r\n' \
29         'Content-Disposition: attachment;filename=%s\r\n' \
30         '\r\n' % filename
31
32 def header(req):
33     return '''<!DOCTYPE html
34     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
35     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
36 <html>
37     <head>
38         <title>SUWI - Sercom Ugly Web Interface</title>
39         <style type="text/css">
40             <!--
41             body
42             {
43                 font-family: sans-serif;
44                 background-color: rgb(255, 255, 255);
45             }
46             table
47             {
48                 border: medium black solid;
49                 border-collapse: collapse;
50             }
51             th
52             {
53                 border: thin black solid;
54                 color: white;
55                 background-color: navy;
56                 padding: 3pt;
57                 text-align: center;
58                 vertical-align: middle;
59             }
60             td
61             {
62                 border: thin black solid;
63                 padding: 3pt;
64                 vertical-align: middle;
65             }
66             .warn
67             {
68                 color: red;
69             }
70             // -->
71         </style>
72     </head>
73     <body>
74 '''
75     pass
76
77 def footer(req):
78     return '''
79     </body>
80 </html>
81 '''
82     pass
83
84 def form(req, submit, str=None):
85     r = submit
86     if submit is not None:
87         r = '<form method="post">\n'
88         if str: r += str
89         r += '<input type="submit" value="%s">\n' % submit
90         r += '</form>\n'
91     return r
92
93 def pre(s):
94     return '<pre>%s</pre>' % cgi.escape(str(s))
95
96 def input_login(req):
97     return '<input type="hidden" name="pw" value="%s" />\n' % PASSWD
98
99 def input_curso(req, curso_id):
100     return input_login(req) \
101         + '<input type="hidden" name="curso" value="%d" />\n' % curso_id
102
103 def input_entrega(req, entrega_id):
104     e = Entrega.get(entrega_id, connection=conn)
105     return input_curso(req, e.curso.id) \
106         + '<input type="hidden" name="entrega" value="%d" />\n' % entrega_id
107
108 def input_zip(req, entrega_id):
109     return input_entrega(req, entrega_id) \
110         + '<input type="hidden" name="zip" value="1" />\n'
111
112 def input_inscripto(req, inscripto_id=None):
113     if inscripto_id is not None:
114         return '<input type="hidden" name="inscripto" value="%d" />\n' \
115             % inscripto_id
116     return ''
117
118 def input_pruebas(req, intento_id, inscripto_id=None):
119     i = Intento.get(intento_id, connection=conn)
120     r = input_entrega(req, i.entrega.id)
121     r += '<input type="hidden" name="intento" value="%d" />\n' % intento_id
122     r += input_inscripto(req, inscripto_id)
123     return r
124
125 def input_intentos(req, entrega_id, inscripto_id):
126     return input_entrega(req, entrega_id) + input_inscripto(req, inscripto_id)
127
128 def login(req):
129     r = '<h1>Bienvenido a ' \
130         '<acronym title="Sercom Ugly Web Interface">SUWI</acronym></h1>\n'
131     r += '<p>Debe ingresar la contraseña para seguir...</p>\n'
132     return r + form(req, 'Entrar',
133         '<p>Contraseña: <input type="password" name="pw" /></p>')
134
135 def curso(req):
136     cursos = [c for c in Curso.select(connection=conn) if len(c.entregas)]
137     r = '<h1>Elegir curso</h1>\n'
138     if cursos:
139         r += '<p>Curso: <select name="curso">\n'
140         for c in cursos:
141             r += '\t<option value="%d">%d-%d-%d</option>\n' \
142                 % (c.id, c.anio, c.cuatrimestre, c.curso)
143         r += '</select></p>\n'
144     else:
145         r += '<p>No hay cursos con entregas</p>\n'
146     return form(req, 'Ver', r + input_login(req))
147
148 def entrega(req, curso_id):
149     c = Curso.get(curso_id, connection=conn)
150     r = '<h1>Elegir entrega del curso %d-%d-%d</h1>\n' \
151         % (c.anio, c.cuatrimestre, c.curso)
152     r += '<p>Entrega: <select name="entrega">\n'
153     for e in c.entregas:
154         r += '\t<option value="%d">%d-%d</option>\n' \
155             % (e.id, e.nroEjercicio, e.entrega)
156     r += '</select></p>\n'
157     return form(req, 'Ver', r + input_curso(req, curso_id))
158
159 def pruebas(req, intento_id, inscripto_id=None):
160     def header():
161         return '''<table>
162     <tr>
163         <th>Nombre</th>
164         <th>Pasada</th>
165         <th>Privada</th>
166         <th>Activa</th>
167         <th>Inicio</th>
168         <th>Fin</th>
169         <th>Observaciones</th>
170     <tr>
171 '''
172         pass
173     def footer():
174         r = '</table>\n<p>\n'
175         r += form(req, 'Volver', input_entrega(req, i.entrega.id)
176             + input_inscripto(req, inscripto_id))
177         r += '</p>\n'
178         return r
179     def row(p):
180         return '''
181     <tr>
182         <td>%s</td>
183         <td>%s</td>
184         <td>%s</td>
185         <td>%s</td>
186         <td>%s</td>
187         <td>%s</td>
188         <td>%s</td>
189     </tr>
190 ''' % (p.casoDePrueba.nombre, p.pasada, p.casoDePrueba.privado,
191         p.casoDePrueba.activo, p.inicio, p.fin,
192         pre(p.observaciones))
193
194     i = Intento.get(intento_id, connection=conn)
195     r = '<h1>Pruebas del intento %d del alumno %d</h1>\n' \
196         % (i.numero, i.inscripto.padron)
197     r += header()
198     for p in i.pruebas:
199         r += row(p)
200     r += footer()
201     return r
202
203 def intentos(req, entrega_id, inscripto_id):
204     def header():
205         return '''<table>
206     <tr>
207         <th>Nro</th>
208         <th>Llegada</th>
209         <th>Compila</th>
210         <th>Pruebas</th>
211         <th>Observaciones</th>
212     <tr>
213 '''
214         pass
215     def footer():
216         r = '</table>\n<p>\n'
217         r += form(req, 'Volver', input_entrega(req, entrega_id))
218         r += '</p>\n'
219         return r
220     def row(i):
221         if i.pruebasPasadas: pruebas = 'BIEN'
222         elif not i.compila: pruebas = None
223         else: pruebas = 'MAL'
224         return '''
225     <tr>
226         <td>%d</td>
227         <td>%s</td>
228         <td>%s</td>
229         <td>%s</td>
230         <td>%s</td>
231     </tr>
232 ''' % (i.numero, i.llegada, i.compila,
233         form(req, pruebas, input_pruebas(req, i.id, inscripto_id)),
234         pre(i.observaciones))
235
236     r = '<h1>Intentos del alumno %d</h1>\n' \
237         % Inscripto.get(inscripto_id, connection=conn).padron
238     r += header()
239     for i in Intento.selectBy(entregaID=entrega_id, inscriptoID=inscripto_id,
240             connection=conn):
241         r += row(i)
242     r += footer()
243     return r
244
245 def zip(req, entrega_id):
246     def zip_path(path, base, zipfd):
247         paths = os.listdir(path)
248         for p in paths:
249             if os.path.isdir(p):
250                 zip_path(os.path.join(path, p), os.path.join(base, p), zipfd)
251             else:
252                 zipfd.write(os.path.join(path, p), os.path.join(base, p))
253
254     from zipfile import ZipFile, ZIP_DEFLATED
255     e = Entrega.get(entrega_id, connection=conn)
256     c = e.curso
257     req.write(http_header_zip(req, 'entrega-%d.%d.%d-%d.%d.zip'
258         % (c.anio, c.cuatrimestre, c.curso, e.nroEjercicio, e.entrega)))
259     tmpfname = os.tmpnam()
260     zipfd = ZipFile(tmpfname, 'w', ZIP_DEFLATED)
261     for c in e.correcciones:
262         zip_path(os.path.join(conf.get('general', 'data_dir'), c.intento.path),
263             str(c.intento.inscripto.padron), zipfd)
264     zipfd.close()
265     req.write(file(tmpfname, 'r').read())
266     os.unlink(tmpfname)
267
268 def correcciones(req, entrega_id):
269     def header():
270         return '''<table>
271     <tr>
272         <th>Padrón</th>
273         <th>Pruebas</th>
274         <th>Intentos</th>
275     <tr>
276 '''
277         pass
278     def footer():
279         r = '</table>\n<p>\n'
280         r += form(req, 'Elegir curso', input_login(req))
281         r += form(req, 'Elegir entrega', input_curso(req, e.curso.id))
282         r += form(req, 'Bajar entrega en .zip', input_zip(req, entrega_id))
283         r += '</p>\n'
284         return r
285     def row(c):
286         if c.intento.pruebasPasadas: pruebas = 'BIEN'
287         elif not c.intento.compila: prubas = None
288         else: pruebas = 'MAL'
289         intentos = int(Intento.selectBy(inscriptoID=c.inscriptoID,
290             entregaID=c.entregaID, connection=conn).count())
291         return '''
292     <tr>
293         <td>%d</td>
294         <td>%s</td>
295         <td>%s</td>
296     </tr>
297 ''' % (c.inscripto.padron,
298         form(req, pruebas, input_pruebas(req, c.intento.id)),
299         form(req, intentos, input_intentos(req, c.entrega.id, c.inscripto.id)))
300
301     e = Entrega.get(entrega_id, connection=conn)
302     c = e.curso
303     r = '<h1>Entrega %d.%d del curso %d-%d-%d</h1>\n' \
304         % (e.nroEjercicio, e.entrega, c.anio, c.cuatrimestre, c.curso)
305     r += header()
306     for c in e.correcciones:
307         r += row(c)
308     r += footer()
309     return r
310
311 #
312 # MAIN
313 #
314
315 req = sys.stdout
316 f = cgi.FieldStorage()
317 raw = f.has_key('zip')
318
319
320 if not raw:
321     print http_header_html(req)
322     print header(req)
323
324 path = os.getenv('PATH_INFO')
325
326 if not f.has_key('pw'):
327     print login(req)
328 elif f.has_key('pw') and f.getfirst('pw') <> PASSWD:
329     print login(req)
330     print '<p class="warn">Password Incorrecto!</p>\n'
331 elif not f.has_key('curso'):
332     print curso(req)
333 elif not f.has_key('entrega'):
334     print entrega(req, int(f.getfirst('curso')))
335 elif f.has_key('intento'):
336     inscripto_id = None
337     if f.has_key('inscripto'):
338         inscripto_id = int(f.getfirst('inscripto'))
339     print pruebas(req, int(f.getfirst('intento')), inscripto_id)
340 elif f.has_key('inscripto'):
341     print intentos(req, int(f.getfirst('entrega')), int(f.getfirst('inscripto')))
342 elif f.has_key('zip'):
343     zip(req, int(f.getfirst('entrega')))
344 else:
345     print correcciones(req, int(f.getfirst('entrega')))
346
347 if not raw:
348     print footer(req)
349