]> git.llucax.com Git - software/sercom-old.git/blob - src/sercom/sqlo.py
Nuevo comando para hacer la entrega final de una entrega: sc_deliver.
[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', joinMethodName='casosDePrueba') # XXX hack
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     def _get_path(self):
159         curso = self.inscripto.curso
160         entrega = self.entrega
161         return path.join(dir_base, 'intentos',
162             '%s.%s' % (curso.anio, curso.cuatrimestre),
163             '%s.%s.%s' % (curso.curso, entrega.nroEjercicio, entrega.entrega),
164             '%s.%s' % (self.inscripto.padron, self.numero))
165
166     def _get_chrootPath(self):
167         return path.join(self.path, 'chroot')
168
169     def _get_pruebasPasadas(self):
170         for p in self.pruebas:
171             if not p.pasada:
172                 return False
173         return True
174
175     def _get_pruebasPublicasPasadas(self):
176         for p in self.pruebas:
177             if not p.pasada and not p.casoDePrueba.privado:
178                 return False
179         return True
180
181     def _get_pruebasPrivadasPasadas(self):
182         for p in self.pruebas:
183             if not p.pasada and p.casoDePrueba.privado:
184                 return False
185         return True
186
187 class Correccion(BaseSQLObject):
188     # Clave
189     entrega         = ForeignKey('Ejercicio')
190     inscripto       = ForeignKey('Inscripto')
191     # Campos
192     intento         = ForeignKey('Intento')
193     docente         = ForeignKey('Docente')
194     nota            = IntCol(default = None)
195     observaciones   = StringCol(default = None)
196
197 class Prueba(BaseSQLObject):
198     # Clave
199     intento         = ForeignKey('Intento')
200     casoDePrueba    = ForeignKey('CasoDePrueba')
201     # Campos
202     inicio          = DateTimeCol()
203     fin             = DateTimeCol(default = None)
204     pasada          = BoolCol(default = None)
205     observaciones   = StringCol(default = None)
206
207     def _get_archivosSalida(self):
208         ent = self.casoDePrueba.archivosEntrada
209         sal = self.casoDePrueba.archivosSalida
210         return frozenset([f for f in os.listdir(self.intento.chrootPath) \
211                     if f in sal or f not in ent and f <> 'tp'])
212
213 # vim: set et sw=4 sts=4 :