1 from sqlobject import *
2 from sqlobject.sqlbuilder import *
6 from datetime import datetime
8 __all__ = ('Curso', 'Inscripto', 'Docente', 'Ejercicio', 'Entrega',
9 'CasoDePrueba', 'Intento', 'Correccion', 'Prueba')
11 # Directorio con los datos por default
14 class BaseSQLObject(SQLObject):
19 return cls.selectBy(limit=1, **kw)[0]
21 raise SQLObjectNotFound, "The object %s with columns %s does not exist" % (cls.__name__, kw)
23 class Curso(BaseSQLObject):
26 cuatrimestre = IntCol()
29 descripcion = StringCol()
31 docentes = RelatedJoin('Docente')
32 entregas = MultipleJoin('Entrega')
33 inscriptos = MultipleJoin('Inscripto')
34 ejercicios = RelatedJoin('Curso', intermediateTable = 'entrega')
36 class Inscripto(BaseSQLObject):
38 padron = IntCol(alternateID=True)
40 curso = ForeignKey('Curso')
42 activo = BoolCol(default=True)
44 intentos = MultipleJoin('Intento')
45 correcciones = MultipleJoin('Correccion')
47 class Docente(BaseSQLObject):
49 nombre = StringCol(alternateID=True)
54 cursos = RelatedJoin('Curso')
55 ejercicios = MultipleJoin('Ejercicio')
56 correcciones = MultipleJoin('Correccion')
58 class Ejercicio(BaseSQLObject):
63 docente = ForeignKey('Docente')
65 casosDePrueba = MultipleJoin('CasoDePrueba')
66 entregas = MultipleJoin('Entrega')
67 cursos = RelatedJoin('Curso', intermediateTable = 'entrega')
70 return path.join(dir_base, 'ejercicios', str(self.id))
72 class Entrega(BaseSQLObject):
74 curso = ForeignKey('Curso')
75 nroEjercicio = IntCol()
78 ejercicio = ForeignKey('Ejercicio')
81 finalizada = BoolCol(default=False)
83 cursos = MultipleJoin('Curso')
84 correcciones = MultipleJoin('Correccion')
85 intentos = MultipleJoin('Intento')
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)
93 class CasoDePrueba(BaseSQLObject):
95 ejercicio = ForeignKey('Ejercicio')
99 activo = BoolCol(default=True)
100 parametros = StringCol(default=None)
101 codigoRetorno = IntCol(default=False)
102 tiempoCpu = FloatCol(default=None)
104 pruebas = MultipleJoin('Prueba')
107 return path.join(self.ejercicio.path, 'casos_de_prueba', self.nombre)
109 def _get_pathEntradas(self):
110 return path.join(self.path, 'entradas')
112 def _get_pathSalidas(self):
113 return path.join(self.path, 'salidas')
115 def _get_archivosEntrada(self):
117 return frozenset(os.listdir(self.pathEntradas))
118 except OSError, (err, msg):
119 if err == errno.ENOENT:
124 def _get_archivosSalida(self):
126 return frozenset(os.listdir(self.pathSalidas))
127 except OSError, (err, msg):
128 if err == errno.ENOENT:
133 class Intento(BaseSQLObject):
135 inscripto = ForeignKey('Inscripto')
136 entrega = ForeignKey('Entrega')
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)
148 pruebas = MultipleJoin('Prueba')
151 def getProximoAProbar(cls, connection=None):
153 return cls.select(cls.q.compila == None, limit=1,
154 orderBy=cls.q.llegada, connection=connection)[0]
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
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))
174 def _get_chrootPath(self):
175 return path.join(self.path, 'chroot')
177 def _get_pruebasPasadas(self):
178 if not self.compila: return False
179 for p in self.pruebas:
180 if not p.pasada: return False
183 def _get_pruebasPublicasPasadas(self):
184 if not self.compila: return False
185 for p in self.pruebas:
186 if not p.pasada and not p.casoDePrueba.privado:
190 def _get_pruebasPrivadasPasadas(self):
191 if not self.compila: return False
192 for p in self.pruebas:
193 if not p.pasada and p.casoDePrueba.privado:
197 class Correccion(BaseSQLObject):
199 entrega = ForeignKey('Entrega')
200 inscripto = ForeignKey('Inscripto')
202 intento = ForeignKey('Intento')
203 docente = ForeignKey('Docente')
204 nota = IntCol(default=None)
205 observaciones = StringCol(default=None)
207 class Prueba(BaseSQLObject):
209 intento = ForeignKey('Intento')
210 casoDePrueba = ForeignKey('CasoDePrueba')
212 inicio = DateTimeCol()
213 fin = DateTimeCol(default=None)
214 pasada = BoolCol(default=None)
215 observaciones = StringCol(default=None)
217 def _get_archivosSalida(self):
218 ent = self.casoDePrueba.archivosEntrada
219 sal = self.casoDePrueba.archivosSalida
220 return frozenset([f for f in os.listdir(self.intento.chrootPath) \
221 if f in sal or f not in ent and f <> 'tp'])
223 # vim: set et sw=4 sts=4 :