]> git.llucax.com Git - software/sercom-old.git/blob - src/sercom/sqlo.py
Se agrega un chequeo a sc_deliver para que no finalice la entrega hasta que no
[software/sercom-old.git] / src / sercom / sqlo.py
1 from sqlobject import *
2 from sqlobject.sqlbuilder import *
3 import errno
4 import os
5 from os import path
6 from datetime import datetime
7
8 __all__ = ('Curso', 'Inscripto', 'Docente', 'Ejercicio', 'Entrega',
9            'CasoDePrueba', 'Intento', 'Correccion', 'Prueba')
10
11 # Directorio con los datos por default
12 dir_base = '.'
13
14 class BaseSQLObject(SQLObject):
15
16     @classmethod
17     def by(cls, **kw):
18         try:
19             return cls.selectBy(limit=1, **kw)[0]
20         except IndexError:
21             raise SQLObjectNotFound, "The object %s with columns %s does not exist" % (cls.__name__, kw)
22
23 class Curso(BaseSQLObject):
24     # Clave
25     anio            = IntCol()
26     cuatrimestre    = IntCol()
27     curso           = IntCol()
28     # Campos
29     descripcion     = StringCol()
30     # Joins
31     docentes        = RelatedJoin('Docente')
32     entregas        = MultipleJoin('Entrega')
33     inscriptos      = MultipleJoin('Inscripto')
34     ejercicios      = RelatedJoin('Curso', intermediateTable = 'entrega')
35
36 class Inscripto(BaseSQLObject):
37     # Clave
38     padron          = IntCol(alternateID=True)
39     # Campos
40     curso           = ForeignKey('Curso')
41     mail            = StringCol()
42     activo          = BoolCol(default=True)
43     # Joins
44     intentos        = MultipleJoin('Intento')
45     correcciones    = MultipleJoin('Correccion')
46
47 class Docente(BaseSQLObject):
48     # Clave
49     nombre          = StringCol(alternateID=True)
50     # Campos
51     mail            = StringCol()
52     corrige         = BoolCol()
53     # Joins
54     cursos          = RelatedJoin('Curso')
55     ejercicios      = MultipleJoin('Ejercicio')
56     correcciones    = MultipleJoin('Correccion')
57
58 class Ejercicio(BaseSQLObject):
59     # Clave
60     nombre          = Col()
61     # Campos
62     numero          = Col()
63     docente         = ForeignKey('Docente')
64     # Joins
65     casosDePrueba   = MultipleJoin('CasoDePrueba')
66     entregas        = MultipleJoin('Entrega')
67     cursos          = RelatedJoin('Curso', intermediateTable = 'entrega')
68
69     def _get_path(self):
70         return path.join(dir_base, 'ejercicios', str(self.id))
71
72 class Entrega(BaseSQLObject):
73     # Clave
74     curso           = ForeignKey('Curso')
75     nroEjercicio    = IntCol()
76     entrega         = IntCol()
77     # Campos
78     ejercicio       = ForeignKey('Ejercicio')
79     desde           = DateTimeCol()
80     hasta           = DateTimeCol()
81     finalizada      = BoolCol(default=False)
82     # Joins
83     cursos          = MultipleJoin('Curso')
84     correcciones    = MultipleJoin('Correccion')
85     intentos        = MultipleJoin('Intento')
86
87     @classmethod
88     def getPendientes(cls, connection=None):
89         return cls.select((cls.q.finalizada == False)
90             & (cls.q.hasta <= datetime.now()),
91             orderBy=cls.q.hasta, connection=connection)
92
93 class CasoDePrueba(BaseSQLObject):
94     # Clave
95     ejercicio       = ForeignKey('Ejercicio')
96     nombre          = StringCol()
97     # Campos
98     privado         = BoolCol()
99     activo          = BoolCol(default=True)
100     parametros      = StringCol(default=None)
101     codigoRetorno   = IntCol(default=False)
102     tiempoCpu       = FloatCol(default=None)
103     # Joins
104     pruebas         = MultipleJoin('Prueba')
105
106     def _get_path(self):
107         return path.join(self.ejercicio.path, 'casos_de_prueba', self.nombre)
108
109     def _get_pathEntradas(self):
110         return path.join(self.path, 'entradas')
111
112     def _get_pathSalidas(self):
113         return path.join(self.path, 'salidas')
114
115     def _get_archivosEntrada(self):
116         try:
117             return frozenset(os.listdir(self.pathEntradas))
118         except OSError, (err, msg):
119             if err == errno.ENOENT:
120                 return frozenset()
121             else:
122                 raise
123
124     def _get_archivosSalida(self):
125         try:
126             return frozenset(os.listdir(self.pathSalidas))
127         except OSError, (err, msg):
128             if err == errno.ENOENT:
129                 return frozenset()
130             else:
131                 raise
132
133 class Intento(BaseSQLObject):
134     # Clave
135     inscripto       = ForeignKey('Inscripto')
136     entrega         = ForeignKey('Entrega')
137     numero          = IntCol()
138     # Campos
139     llegada         = DateTimeCol()
140     inicioCompila   = DateTimeCol(default=None)
141     finCompila      = DateTimeCol(default=None)
142     inicioPruebas   = DateTimeCol(default=None)
143     finPruebas      = DateTimeCol(default=None)
144     compila         = BoolCol(default=None)
145     mailRespuesta   = StringCol()
146     observaciones   = StringCol(default=None)
147     # Joins
148     pruebas         = MultipleJoin('Prueba')
149
150     @classmethod
151     def getProximoAProbar(cls, connection=None):
152         try:
153             return cls.select(cls.q.compila == None, limit=1,
154                 orderBy=cls.q.llegada, connection=connection)[0]
155         except IndexError:
156             return None
157
158     @classmethod
159     def faltaCompilar(cls, entrega, connection=None):
160         no_compilados = cls.selectBy(entregaID=entrega.id, compila=None,
161             connection=connection).count()
162         no_probados = cls.selectBy(entregaID=entrega.id, compila=True,
163             finPruebas=None, connection=connection).count()
164         return no_compilados + no_probados
165
166     def _get_path(self):
167         curso = self.inscripto.curso
168         entrega = self.entrega
169         return path.join(dir_base, 'intentos',
170             '%s.%s' % (curso.anio, curso.cuatrimestre),
171             '%s.%s.%s' % (curso.curso, entrega.nroEjercicio, entrega.entrega),
172             '%s.%s' % (self.inscripto.padron, self.numero))
173
174     def _get_chrootPath(self):
175         return path.join(self.path, 'chroot')
176
177     def _get_pruebasPasadas(self):
178         for p in self.pruebas:
179             if not p.pasada:
180                 return False
181         return True
182
183     def _get_pruebasPublicasPasadas(self):
184         for p in self.pruebas:
185             if not p.pasada and not p.casoDePrueba.privado:
186                 return False
187         return True
188
189     def _get_pruebasPrivadasPasadas(self):
190         for p in self.pruebas:
191             if not p.pasada and p.casoDePrueba.privado:
192                 return False
193         return True
194
195 class Correccion(BaseSQLObject):
196     # Clave
197     entrega         = ForeignKey('Entrega')
198     inscripto       = ForeignKey('Inscripto')
199     # Campos
200     intento         = ForeignKey('Intento')
201     docente         = ForeignKey('Docente')
202     nota            = IntCol(default=None)
203     observaciones   = StringCol(default=None)
204
205 class Prueba(BaseSQLObject):
206     # Clave
207     intento         = ForeignKey('Intento')
208     casoDePrueba    = ForeignKey('CasoDePrueba')
209     # Campos
210     inicio          = DateTimeCol()
211     fin             = DateTimeCol(default=None)
212     pasada          = BoolCol(default=None)
213     observaciones   = StringCol(default=None)
214
215     def _get_archivosSalida(self):
216         ent = self.casoDePrueba.archivosEntrada
217         sal = self.casoDePrueba.archivosSalida
218         return frozenset([f for f in os.listdir(self.intento.chrootPath) \
219                     if f in sal or f not in ent and f <> 'tp'])
220
221 # vim: set et sw=4 sts=4 :