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