class SOTupleCol(SOPickleCol):
def createValidators(self):
- return [TupleValidator(name=self.name)]
+ return [TupleValidator(name=self.name, pickleProtocol=self.pickleProtocol)]
class TupleCol(PickleCol):
baseClass = SOTupleCol
class Usuario(InheritableSQLObject): #{{{
# Clave (para docentes puede ser un nombre de usuario arbitrario)
- usuario = UnicodeCol(length=10, alternateID=True)
+ usuario = UnicodeCol(length=10, alternateID=True,
+ alternateMethodName='by_usuario')
# Campos
contrasenia = UnicodeCol(length=255, default=None)
nombre = UnicodeCol(length=255, notNone=True)
def _get_user_name(self): # para identity
return self.usuario
+ @classmethod
+ def byUsuario(cls, usuario): # TODO eliminar, backward compat
+ return cls.by_usuario(usuario)
+
@classmethod
def by_user_name(cls, user_name): # para identity
user = cls.byUsuario(user_name)
class Docente(Usuario): #{{{
_inheritable = False
# Campos
- nombrado = BoolCol(notNone=True, default=True)
+ nombrado = BoolCol(notNone=True, default=True)
# Joins
- enunciados = MultipleJoin('Enunciado', joinColumn='autor_id')
- cursos = MultipleJoin('DocenteInscripto')
+ enunciados = MultipleJoin('Enunciado', joinColumn='autor_id')
+ inscripciones = MultipleJoin('DocenteInscripto')
def add_entrega(self, instancia, **kw):
return Entrega(instancia=instancia, **kw)
self.usuario = padron
@classmethod
- def byPadron(cls, padron):
+ def byPadron(cls, padron): # TODO eliminar, backward compat
return cls.byUsuario(unicode(padron))
+ @classmethod
+ def by_padron(cls, padron):
+ return cls.by_usuario(unicode(padron))
+
def __repr__(self):
return 'Alumno(id=%s, padron=%s, nombre=%s, password=%s, email=%s, ' \
'telefono=%s, activo=%s, creado=%s, observaciones=%s)' \
# Joins
comandos = MultipleJoin('ComandoPrueba', joinColumn='tarea_id')
- def add_comando(self, orden, **kw):
- return ComandoPrueba(tarea=self, orden=orden, comando='', **kw)
+ def add_comando(self, orden, comando='', **kw):
+ return ComandoPrueba(tarea=self, orden=orden, comando=comando, **kw)
def remove_comando(self, orden):
ComandoPrueba.pk.get(self.id, orden).destroySelf()
max_locks_memoria = IntCol(default=None)
terminar_si_falla = BoolCol(notNone=True, default=True)
rechazar_si_falla = BoolCol(notNone=True, default=True)
+ publico = BoolCol(notNone=True, default=True)
archivos_entrada = BLOBCol(default=None) # ZIP con archivos de entrada
# __stdin__ es caso especial
# Si un caso de prueba tiene
- # comandos con stdin y el caso
- # de prueba también tiene stdin
- # se usa el stdin del comando.
+ # comandos que tiene algún
+ # archivo de entrada (incluyendo
+ # stdin) con los propios, se usa
+ # el archivo del caso de prueba,
+ # no del comando.
archivos_a_comparar = BLOBCol(default=None) # ZIP con archivos de salida
# __stdout__, __stderr__ y
# __stdouterr__ (ambos juntos)
# son casos especiales
- archivos_a_guardar = TupleCol(notNone=True, default=()) # TODO SetCol
+ # Si un caso de prueba tiene
+ # comandos que tiene algún
+ # archivo a comparar (incluyendo
+ # stdout/err) con los propios,
+ # se compara contra el archivo
+ # del caso de prueba, no del
+ # comando.
+ archivos_a_guardar = TupleCol(notNone=True, default=()) # TODO FrozenSetCol
# __stdout__, __stderr__ y
# __stdouterr__ (ambos juntos)
# son casos especiales
class ComandoPrueba(Comando): #{{{
_inheritable = False
- RET_PRUEBA = -2 # Espera el mismo retorno que el de la prueba.
+ RET_PRUEBA = -257 # Espera el mismo retorno que el de la prueba.
# XXX todos los campos de limitación en este caso son multiplicadores para
# los valores del caso de prueba.
# Clave
descripcion = UnicodeCol(length=255, default=None)
autor = ForeignKey('Docente', cascade='null')
creado = DateTimeCol(notNone=True, default=DateTimeCol.now)
- archivo = BLOBCol(default=None)
- archivo_name = UnicodeCol(length=255, default=None)
- archivo_type = UnicodeCol(length=255, default=None)
+ archivos = BLOBCol(default=None)
# Joins
ejercicios = MultipleJoin('Ejercicio')
casos_de_prueba = MultipleJoin('CasoDePrueba')
pruebas = MultipleJoin('Prueba')
def __repr__(self):
- return super(ComandoFuente, self).__repr__('enunciado=%s, nombre=%s'
+ return super(CasoDePrueba, self).__repr__('enunciado=%s, nombre=%s'
% (srepr(self.enunciado), self.nombre))
def shortrepr(self):
# Campos
inicio = DateTimeCol(notNone=True)
fin = DateTimeCol(notNone=True)
- procesada = BoolCol(notNone=True, default=False)
- observaciones = UnicodeCol(default=None)
+ inicio_proceso = DateTimeCol(default=None)
+ fin_proceso = DateTimeCol(default=None)
+ observaciones = UnicodeCol(notNone=True, default=u'')
activo = BoolCol(notNone=True, default=True)
# Joins
entregas = MultipleJoin('Entrega', joinColumn='instancia_id')
def __repr__(self):
return 'InstanciaDeEntrega(id=%s, numero=%s, inicio=%s, fin=%s, ' \
- 'procesada=%s, observaciones=%s, activo=%s)' \
+ 'inicio_proceso=%s, fin_proceso=%s, observaciones=%s, activo=%s)' \
% (self.id, self.numero, self.inicio, self.fin,
- self.procesada, self.observaciones, self.activo)
+ self.inicio_proceso, self.fin_proceso, self.observaciones,
+ self.activo)
def shortrepr(self):
return self.numero
def add_miembro(self, alumno, **kw):
if isinstance(alumno, AlumnoInscripto):
alumno = alumno.id
- return Miembro(grupo=self, alumnoID=alumno, **kw)
+ # FIXME acá habría que sacarle la unicidad a Miembro.pk para que
+ # un alumno pueda ser miembro varias veces del mismo grupo, de
+ # manera de tener la historia completa, pero hay que tener cuidad
+ # y arreglar todos los lugares donde se asume esa unicidad
+ try:
+ m = Miembro.selectBy(grupo=self, alumnoID=alumno).getOne()
+ m.baja = None # si ya existía, le sacamos la fecha de baja
+ return m
+ except SQLObjectNotFound: # creo uno nuevo
+ return Miembro(grupo=self, alumnoID=alumno, **kw)
def remove_miembro(self, alumno):
if isinstance(alumno, AlumnoInscripto):
def add_tutor(self, docente, **kw):
if isinstance(docente, DocenteInscripto):
docente = docente.id
- return Tutor(grupo=self, docenteID=docente, **kw)
+ # FIXME ídem add_miembro()
+ try:
+ t = Tutor.selectBy(grupo=self, docenteID=docente).getOne()
+ t.baja = None # si ya existía, le sacamos la fecha de baja
+ return t
+ except SQLObjectNotFound: # creo uno nuevo
+ return Tutor(grupo=self, docenteID=docente, **kw)
def remove_tutor(self, docente):
if isinstance(docente, DocenteInscripto):
@classmethod
def selectByAlumno(self, alumno):
return Miembro.select(AND(Miembro.q.alumnoID == AlumnoInscripto.q.id,
- AlumnoInscripto.q.alumnoID == alumno.id))
+ AlumnoInscripto.q.alumnoID == alumno.id, Miembro.q.baja == None))
def shortrepr(self):
return 'grupo:' + self.nombre
membresias = MultipleJoin('Miembro', joinColumn='alumno_id')
entregas = MultipleJoin('Entrega', joinColumn='alumno_id')
correcciones = MultipleJoin('Correccion', joinColumn='alumno_id')
+ # Notas de la cursada
+ nota_practica = DecimalCol(size=3, precision=1, default=None)
+ nota_final = DecimalCol(size=3, precision=1, default=None)
+ nota_libreta = DecimalCol(size=3, precision=1, default=None)
def _get_nombre(self):
return self.alumno.padron
class Ejecucion(InheritableSQLObject): #{{{
# Campos
- inicio = DateTimeCol(notNone=True, default=DateTimeCol.now)
+ inicio = DateTimeCol(default=None)
fin = DateTimeCol(default=None)
exito = IntCol(default=None)
observaciones = UnicodeCol(notNone=True, default=u'')
# FIXME self.id, caso_de_prueba
Prueba.pk.get(self.id, caso_de_prueba).destroySelf()
+ def make_correccion(self, corrector, **kw):
+ return Correccion(instancia=self.instancia, entregador=self.entregador,
+ entrega=self, corrector=corrector, **kw)
+
def __repr__(self):
return super(Entrega, self).__repr__('instancia=%s, entregador=%s, '
'fecha=%s' % (self.instancia.shortrepr(), srepr(self.entregador),
pk = DatabaseIndex(instancia, entregador, unique=True)
# Campos
entrega = ForeignKey('Entrega', notNone=True, cascade=False)
- corrector = ForeignKey('DocenteInscripto', default=None, cascade='null')
+ corrector = ForeignKey('DocenteInscripto', notNone=True, cascade=False)
asignado = DateTimeCol(notNone=True, default=DateTimeCol.now)
corregido = DateTimeCol(default=None)
nota = DecimalCol(size=3, precision=1, default=None)
diferencias = BLOBCol(default=None) # ZIP con archivos guardados
def __repr__(self, clave='', mas=''):
- return super(ComandoFuenteEjecutado, self).__repr__(clave, mas)
+ return super(ComandoEjecutado, self).__repr__(clave, mas)
#}}}
class ComandoFuenteEjecutado(ComandoEjecutado): #{{{
def __repr__(self):
return super(ComandoPruebaEjecutado, self).__repr__(
- 'comando=%s, entrega=%s' % (self.comando.shortrepr(),
- self.entrega.shortrepr()))
+ 'comando=%s, prueba=%s' % (self.comando.shortrepr(),
+ self.prueba.shortrepr()))
def shortrepr(self):
- return '%s:%s:%s' % (self.tarea.shortrepr(), self.entrega.shortrepr(),
+ return '%s:%s:%s' % (self.tarea.shortrepr(), self.prueba.shortrepr(),
self.caso_de_prueba.shortrepr())
#}}}
# Campos
descripcion = UnicodeCol(length=255, default=None)
creado = DateTimeCol(notNone=True, default=datetime.now)
- permisos = TupleCol(notNone=True)
+ permisos = TupleCol(notNone=True, length=2**16)
# Joins
usuarios = RelatedJoin('Usuario', addRemoveName='_usuario')