Skip to content

Commit

Permalink
Incluir en CorrectorTask el alu_repo a donde sincronizar la entrega
Browse files Browse the repository at this point in the history
Estos son los cambios requeridos en el "backend" (corrector.py), lo
siguiente es que el frontend (main.py) complete el campo alu_repo de
la tarea CorregirTask—leyendo para ello la planilla, y las guidelines
de algoritmos-rw#49.

Como seguramente haga merge de este PR una vez a la par que el PR del
front-end, voy a decir que this closes: algoritmos-rw#51.
  • Loading branch information
dato committed Sep 25, 2020
1 parent d6336e2 commit a02e91b
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 35 deletions.
11 changes: 11 additions & 0 deletions algorw/common/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from dataclasses import dataclass, field


@dataclass
class Repo:
name: str = field(init=False)
owner: str = field(init=False)
full_name: str

def __post_init__(self):
self.owner, self.name = self.full_name.split("/", 1)
31 changes: 21 additions & 10 deletions algorw/common/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,40 @@

from pydantic import BaseModel

from .models import Repo


class CorrectorTask(BaseModel):
"""Clase que se encola en Redis para procesar por el worker.
"""
"""Clase que se encola en Redis para procesar por el corrector.
# Por el momento, esta clase solo actúa de wrapper "legacy" para los
# correos que el sistema de entregas envía a Gmail. Como primer paso
# en la reescritura, el corrector ahora los obtiene de Redis. Gmail
# actúa ahora como backup (se le puede aplicar la etiqueta ‘entregas’
# a un mail para que el corrector lo vuelva a procesar). A futuro, esta
# clase irá teniendo todos los campos necesarios para que el corrector
# no necesite parsear nada.
La cola de rq es ahora la principal comunicación entre el sistema de
entregas y el corrector. Gmail actua ahora como backup, o “corrector
legacy” (procesa y corrige las entregas, pero no envía el correo de
respuesta a les alumnes; este correo queda solo en la casilla).
"""

# "tp_id es el ID del TP; suele ir en minúsculas, y se usa como nombre
# de directorio en skel.
tp_id: str
zipfile: bytes
legajos: List[str]

# "orig_headers" son los headers del correo original que envió el sistema
# de entregas. TODO: eliminar de corrector.py toda la lógica que trata la
# entrada como un correo.
orig_headers: Dict[str, str]
group_id: Optional[str] = None

# Ubicación de la entrega en el repo de entregas. A día de hoy el sistema
# de entregas elige la ruta, y el corrector guarda los archivos. Próximamente,
# el sistema de entregas guardará los archivos, y el corrector los leerá.
repo_relpath: PurePath

# "group_id" está presente para entregas grupales con ID de grupo. "alu_repo",
# si está presente, es el repositorio a donde se debería sincronizar la entrega
# (usando "github_id" para la autoría de los commits, o "wachenbot" si no).
group_id: Optional[str] = None
alu_repo: Optional[Repo] = None
github_id: Optional[str] = None

class Config:
arbitrary_types_allowed = True
24 changes: 3 additions & 21 deletions algorw/corrector/alu_repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import io
import os
import pathlib
import random
import re
import tempfile

Expand Down Expand Up @@ -34,18 +33,6 @@
GITHUB_TOKEN = os.environ["CORRECTOR_GH_TOKEN"]
DEFAULT_GHUSER = os.environ["CORRECTOR_GH_USER"]

# XXX Temporario 2020/1. Maneja a qué personas se les incluye
# el enlace al repo en el mail que envía el corrector.
REVIEWEE_INDIV = {
"54321",
}

# Poner aquí los padrones de integrantes de grupos, pero *solo*
# si el grupo tiene dos miembros. Si no, ponerlos en REVIEW_INDIV.
REVIEWEE_GRUPAL = {
"543421",
}


class AluRepo:
"""Clase para manejar los repositorios individuales y grupales.
Expand All @@ -57,7 +44,7 @@ class AluRepo:
DEFAULT_COLUMN = "Repo"

def __init__(
self, repo_full: str, legajos: List[str], github_users: List[str] = None,
self, repo_full: str, legajos: List[str], github_user: str = None,
):
"""Constructor de la clase AluRepo.
Expand All @@ -70,7 +57,7 @@ def __init__(
self.gh_repo = None
self.legajos = set(legajos)
self.repo_full = repo_full
self.github_users = github_users or [DEFAULT_GHUSER]
self.github_user = github_user or DEFAULT_GHUSER

@classmethod
def from_legajo(
Expand Down Expand Up @@ -214,11 +201,6 @@ def ensure_exists(self, *, skel_repo: str = None):
# TODO: set up team access
# TODO: configure branch protections

def has_reviewer(self):
# TODO: usar la columna Reviewer de la planilla?
reviewees = REVIEWEE_GRUPAL if len(self.legajos) > 1 else REVIEWEE_INDIV
return not self.legajos.isdisjoint(reviewees)

def sync(self, entrega_dir: pathlib.Path, rama: str, *, target_subdir: str = None):
"""Importa una entrega a los repositorios de alumnes.
Expand All @@ -239,7 +221,7 @@ def sync(self, entrega_dir: pathlib.Path, rama: str, *, target_subdir: str = Non
gh = github.Github(GITHUB_TOKEN)
repo = self.gh_repo or gh.get_repo(self.repo_full)
gitref = repo.get_git_ref(f"heads/{rama}")
ghuser = random.choice(self.github_users) # ¯\_(ツ)_/¯ Only entregas knows.
ghuser = self.github_user
prefix_re = re.compile(re.escape(target_subdir.rstrip("/") + "/"))

# Estado actual del repo.
Expand Down
6 changes: 3 additions & 3 deletions algorw/corrector/corrector.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,18 +163,18 @@ def procesar_entrega(task: CorrectorTask):
if retcode != 0:
raise ErrorInterno(output)

if TODO_OK_REGEX.search(output) and False:
if task.alu_repo is not None:
try:
# Sincronizar la entrega con los repositorios individuales.
alu_repo = AluRepo.from_legajos(padron.split("_"), tp_id)
alu_repo = AluRepo(task.alu_repo.full_name, task.legajos, task.github_id)
alu_repo.ensure_exists(skel_repo="algorw-alu/algo2_tps")
alu_repo.sync(moss.location(), tp_id)
except (KeyError, ValueError):
pass
except GithubException as ex:
print(f"error al sincronizar: {ex}", file=sys.stderr)
else:
if alu_repo.has_reviewer():
if TODO_OK_REGEX.search(output):
# Insertar, por el momento, la URL del repositorio.
# TODO: insertar URL para un pull request si es el primer Todo OK.
message = "Esta entrega fue importada a:"
Expand Down
3 changes: 2 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ def oauth_credentials():
def post():
# Leer valores del formulario.
try:
validate_captcha()
if not cfg.test:
validate_captcha()
tp = request.form["tp"]
files = get_files()
body = request.form["body"] or ""
Expand Down

0 comments on commit a02e91b

Please sign in to comment.