From 245f7025181c555c285d8b598caa180a69c19812 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Sat, 10 Mar 2007 20:00:18 +0000 Subject: [PATCH] =?utf8?q?Ejecutar=20comandos=20con=20shell=20y=20almacena?= =?utf8?q?rlos=20como=20strings.=20Se=20eliminar=20todo=20lo=20relacionado?= =?utf8?q?=20con=20Parametros=20(ParamValidator,=20modulo=20sercom.validat?= =?utf8?q?ors=20-que=20ten=C3=ADa=20s=C3=B3lo=20eso-,=20ParamCol,=20etc.)?= =?utf8?q?=20y=20se=20almacenan=20los=20comandos=20como=20simples=20string?= =?utf8?q?=20porque=20ahora=20se=20ejecutan=20los=20comandos=20usando=20el?= =?utf8?q?=20shell.=20La=20raz=C3=B3n=20para=20no=20hacer=20esto=20en=20el?= =?utf8?q?=20sistema=20viejo=20era=20la=20carencia=20de=20un=20chroot=20co?= =?utf8?q?mpleto,=20cosa=20que=20ahora=20s=C3=AD=20tiene=20el=20sistema.?= =?utf8?q?=20Esto=20adem=C3=A1s=20de=20simplificar=20el=20modelo=20de=20da?= =?utf8?q?tos,=20hace=20mucho=20m=C3=A1s=20flexible=20la=20especificaci?= =?utf8?q?=C3=B3n=20de=20comandos/casos=20de=20prueba,=20ya=20que=20se=20p?= =?utf8?q?ueden=20utilizar=20cosas=20propias=20del=20shell=20(como=20el=20?= =?utf8?q?glob).?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- doc/testdata.py | 6 +- sercom/model.py | 44 +--------- .../subcontrollers/caso_de_prueba/__init__.py | 16 ++-- .../caso_de_prueba/templates/list.kid | 6 +- .../caso_de_prueba/templates/show.kid | 6 +- sercom/tester.py | 12 ++- sercom/validators.py | 88 ------------------- 7 files changed, 26 insertions(+), 152 deletions(-) delete mode 100644 sercom/validators.py diff --git a/doc/testdata.py b/doc/testdata.py index a29b8d6..a461157 100644 --- a/doc/testdata.py +++ b/doc/testdata.py @@ -20,7 +20,7 @@ cf = tf.add_comando(1, 'make tito', retorno=0, max_cant_archivos=15, 'sin usar un Makefile (debe ser un solo archivo que se llame tito.c)') tp = TareaPrueba(nombre='Probar', terminar_si_falla=True, rechazar_si_falla=True) -cp = tp.add_comando(1, [], retorno=0, terminar_si_falla=True, +cp = tp.add_comando(1, retorno=0, terminar_si_falla=True, rechazar_si_falla=True, descripcion='Prueba normalmente, sin filtros') # Enunciados @@ -37,9 +37,9 @@ c = Curso(anio=2007, cuatrimestre=1, numero=1, descripcion=u'Martes', # Casos de prueba cp1 = e1.add_caso_de_prueba(nombre=u'Sin parámetros', retorno=0, - descripcion=u'Un caso', comando=[]) + descripcion=u'Un caso', comando='./tito') cp2 = e1.add_caso_de_prueba(nombre=u'2 parámetross', retorno=0, - comando='--test -c "con espacios"') + comando='./tito --test -c "con espacios"') # Ejercicios ej1 = c.ejercicios[0] diff --git a/sercom/model.py b/sercom/model.py index a99995f..42385e7 100644 --- a/sercom/model.py +++ b/sercom/model.py @@ -8,7 +8,6 @@ from sqlobject.inheritance import InheritableSQLObject from sqlobject.col import PickleValidator, UnicodeStringValidator from turbogears import identity from turbogears.identity import encrypt_password as encryptpw -from sercom.validators import params_to_list, ParseError from formencode import Invalid hub = PackageHub("sercom") @@ -46,43 +45,6 @@ class SOTupleCol(SOPickleCol): class TupleCol(PickleCol): baseClass = SOTupleCol -class ParamsValidator(UnicodeStringValidator): - def to_python(self, value, state): - if isinstance(value, basestring) or value is None: - value = super(ParamsValidator, self).to_python(value, state) - try: - value = params_to_list(value) - except ParseError, e: - raise Invalid("invalid parameters in the ParamsCol '%s', parse " - "error: %s" % (self.name, e), value, state) - elif not isinstance(value, (list, tuple)): - raise Invalid("expected a tuple, list or valid string in the " - "ParamsCol '%s', got %s %r instead" - % (self.name, type(value), value), value, state) - return value - def from_python(self, value, state): - if isinstance(value, (list, tuple)): - value = ' '.join([repr(p) for p in value]) - elif isinstance(value, basestring) or value is None: - value = super(ParamsValidator, self).to_python(value, state) - try: - params_to_list(value) - except ParseError, e: - raise Invalid("invalid parameters in the ParamsCol '%s', parse " - "error: %s" % (self.name, e), value, state) - else: - raise Invalid("expected a tuple, list or valid string in the " - "ParamsCol '%s', got %s %r instead" - % (self.name, type(value), value), value, state) - return value - -class SOParamsCol(SOUnicodeCol): - def createValidators(self): - return [ParamsValidator(db_encoding=self.dbEncoding, name=self.name)] - -class ParamsCol(UnicodeCol): - baseClass = SOParamsCol - #}}} #{{{ Clases @@ -349,8 +311,8 @@ class TareaPrueba(Tarea): #{{{ # Joins comandos = MultipleJoin('ComandoPrueba', joinColumn='tarea_id') - def add_comando(self, orden, comando, **kw): - return ComandoPrueba(tarea=self, orden=orden, comando=comando, **kw) + def add_comando(self, orden, **kw): + return ComandoPrueba(tarea=self, orden=orden, comando='', **kw) def remove_comando(self, orden): ComandoPrueba.pk.get(self.id, orden).destroySelf() @@ -364,7 +326,7 @@ class Comando(InheritableSQLObject): #{{{ RET_ANY = None RET_FAIL = -1 # Campos - comando = ParamsCol(length=255, notNone=True) + comando = UnicodeCol(length=255, notNone=True) descripcion = UnicodeCol(length=255, default=None) retorno = IntCol(default=None) # None es que no importa max_tiempo_cpu = IntCol(default=None) # En segundos diff --git a/sercom/subcontrollers/caso_de_prueba/__init__.py b/sercom/subcontrollers/caso_de_prueba/__init__.py index d931bf5..8c52315 100644 --- a/sercom/subcontrollers/caso_de_prueba/__init__.py +++ b/sercom/subcontrollers/caso_de_prueba/__init__.py @@ -10,7 +10,6 @@ from turbogears import paginate from docutils.core import publish_parts from sercom.subcontrollers import validate as val from sercom.model import CasoDePrueba, Enunciado -from sercom.validators import ParamsValidator #}}} #{{{ Configuración @@ -69,10 +68,10 @@ class CasoDePruebaForm(W.TableForm): validator=V.UnicodeString(not_empty=False, max=255, strip=True)) comando = W.TextField(label=_(u'Comando'), - validator=ParamsValidator(not_empty=False, strip=True)) + validator=V.UnicodeString(not_empty=False, strip=True)) retorno = W.TextField(label=_(u'Código de retorno'), validator=V.Int(not_empty=False, strip=True)) - tiempo_cpu = W.TextField(label=_(u'Tiempo de CPU'), + max_tiempo_cpu = W.TextField(label=_(u'Máximo tiempo de CPU'), validator=V.Number(not_empty=False, strip=True)) fields = Fields() javascript = [W.JSSource("MochiKit.DOM.focusOnLoad('form_nombre');")] @@ -82,9 +81,6 @@ form = CasoDePruebaForm() #{{{ Controlador -def params2str(params): - return ' '.join([repr(p)[1:] for p in params]) - class CasoDePruebaController(controllers.Controller, identity.SecureResource): """Basic model admin interface""" require = identity.has_permission('admin') @@ -107,8 +103,7 @@ class CasoDePruebaController(controllers.Controller, identity.SecureResource): r = cls.select() else: r = cls.selectBy(enunciadoID=enunciado) - return dict(records=r, name=name, namepl=namepl, parcial=enunciado, - params2str=params2str) + return dict(records=r, name=name, namepl=namepl, parcial=enunciado) @expose(template='kid:%s.templates.new' % __name__) def new(self, **kw): @@ -128,8 +123,7 @@ class CasoDePruebaController(controllers.Controller, identity.SecureResource): def edit(self, id, **kw): """Edit record in model""" r = validate_get(id) - return dict(name=name, namepl=namepl, record=r, form=form, - params2str=params2str) + return dict(name=name, namepl=namepl, record=r, form=form) @validate(form=form) @error_handler(edit) @@ -148,7 +142,7 @@ class CasoDePruebaController(controllers.Controller, identity.SecureResource): r.desc = '' else: r.desc = publish_parts(r.descripcion, writer_name='html')['html_body'] - return dict(name=name, namepl=namepl, record=r, params2str=params2str) + return dict(name=name, namepl=namepl, record=r) @expose() def delete(self, id): diff --git a/sercom/subcontrollers/caso_de_prueba/templates/list.kid b/sercom/subcontrollers/caso_de_prueba/templates/list.kid index 356e0f5..c891ae8 100644 --- a/sercom/subcontrollers/caso_de_prueba/templates/list.kid +++ b/sercom/subcontrollers/caso_de_prueba/templates/list.kid @@ -16,7 +16,7 @@ Descripción Parámetros RET - CPU + CPU Operaciones @@ -25,9 +25,9 @@ href="${tg.url('/enunciado/show/%d' % record.enunciado.id)}">enunciado descripción - comando --con-parámetros + comando --con-parámetros retorno - tiempo de cpu + máx tiempo de cpu Editar Eliminar diff --git a/sercom/subcontrollers/caso_de_prueba/templates/show.kid b/sercom/subcontrollers/caso_de_prueba/templates/show.kid index 58700e4..91060cd 100644 --- a/sercom/subcontrollers/caso_de_prueba/templates/show.kid +++ b/sercom/subcontrollers/caso_de_prueba/templates/show.kid @@ -25,7 +25,7 @@ Parámetros: - comando --con-parámetros: + comando --con-parámetros: @@ -33,8 +33,8 @@ retorno - Tiempo de CPU: - tiempo_cpu + Máximo tiempo de CPU: + max_tiempo_cpu diff --git a/sercom/tester.py b/sercom/tester.py index 5915182..4d6cb3f 100644 --- a/sercom/tester.py +++ b/sercom/tester.py @@ -298,9 +298,15 @@ def ejecutar_comando_fuente(self, path, entrega): #{{{ unzip(self.archivos_entrada, path) # TODO try/except comando_ejecutado = entrega.add_comando_ejecutado(self) # Abro archivos para fds básicos (FIXME) - options = dict(close_fds=True, stdin=None, stdout=None, stderr=None, - preexec_fn=SecureProcess(self, 'var/chroot_pepe', '/home/sercom/build')) - log.debug(_(u'Ejecutando como root: %s'), ' '.join(self.comando)) + options = dict( + close_fds=True, + stdin=None, + stdout=None, + stderr=None, + shell=True, + preexec_fn=SecureProcess(self, 'var/chroot_pepe', '/home/sercom/build') + ) + log.debug(_(u'Ejecutando como root: %s'), self.comando) os.seteuid(0) # Dios! (para chroot) os.setegid(0) try: diff --git a/sercom/validators.py b/sercom/validators.py deleted file mode 100644 index 4779006..0000000 --- a/sercom/validators.py +++ /dev/null @@ -1,88 +0,0 @@ -# vim: set et sw=4 sts=4 encoding=utf-8 : - -from turbogears.validators import * - -class ParseError(ValueError): pass - -def params_to_list(params): - r"""Parsea un string de forma similar al bash, separando por espacios y - teniendo en cuenta comillas simples y dobles para agrupar. Para poner - comillas se puede usar el \ como caracter de escape (\' y \") y también - interpreta \n y \t. Devuelve una lista con los parámetros encontrados. - >>> param2seq('--prueba') - ['--prueba'] - >>> params_to_list('--prueba larga "con espacios"') - ['--prueba', 'larga', 'con espacios'] - >>> params_to_list(u'''"con enter\\nentre 'comillas \\"dobles\\"'" --unicode''') - [u'con enter\nentre \'comillas "dobles"\'', u'--unicode'] - >>> params_to_list('"archivo\\tseparado\\tpor\\ttabs" -h') - ['archivo\tseparado\tpor\ttabs', '-h'] - """ - # Constantes - SEP, TOKEN, DQUOTE, SQUOTE = ' ', None, '"', "'" - seq = [] - buff = '' - escape = False - state = SEP - if not params: return seq - for c in params: - # Es un caracter escapado - if escape: - if c == 'n': - buff += '\n' - elif c == 't': - buff += '\t' - else: - buff += c - escape = False - continue - # Es una secuencia de escape - if c == '\\': - escape = True - continue - # Si está buscando espacios - if state == SEP: - if c == SEP: - continue - else: - state = TOKEN # Encontró - if state == TOKEN: - if c == DQUOTE: - state = DQUOTE - continue - if c == SQUOTE: - state = SQUOTE - continue - if c == SEP: - state = SEP - seq.append(buff) - buff = '' - continue - buff += c - continue - if state == DQUOTE: - if c == DQUOTE: - state = TOKEN - continue - buff += c - continue - if state == SQUOTE: - if c == SQUOTE: - state = TOKEN - continue - buff += c - continue - raise ParseError, 'Invalid syntax' - if state == DQUOTE or state == SQUOTE: - raise ParseError, 'Missing closing quote %s' % state - if buff: - seq.append(buff) - return seq - -class ParamsValidator(UnicodeString): - def validate_python(self, value, state): - try: - params_to_list(value) - except ParseError, e: - raise Invalid(str(e), value, state) - -- 2.43.0