Skip to content
Snippets Groups Projects
Commit 879c1eb9 authored by Florian Bruhin's avatar Florian Bruhin
Browse files

Validate selected topic in notebook

Fixes taas#8
parent 9d01f83e
No related branches found
No related tags found
No related merge requests found
Pipeline #235092 failed
......@@ -2,10 +2,12 @@ import datetime
import sys
import time
import zipfile
from typing import Any
from pathlib import Path
import httpx
import typer
import nbformat
from rich import print
from rich.console import Console
from rich.panel import Panel
......@@ -16,6 +18,8 @@ console = Console()
app = typer.Typer()
BASE_URL = "http://localhost:5000"
PROJECT_NB_NAME = "project.ipynb"
PROJECT_TOPIC_COUNT = 2
PROJECT_LIMIT_SOFT_MB = 5
PROJECT_LIMIT_HARD_MB = 50
......@@ -54,6 +58,14 @@ def check_notebook_file(path: Path, force: bool) -> None:
console.print(f"Last change: [bold]{modified}[/bold] {sec} ago{suffix}")
def find_nb_tag(nb: nbformat.NotebookNode, tag: str) -> dict[str, Any]:
for cell in nb.cells:
if tag in cell.metadata.get("tags", []):
return cell
console.print(f"Missing {tag} cell in notebook")
raise CheckError
def check_project_file(path: Path, force: bool) -> None:
size = path.stat().st_size
soft_limit = PROJECT_LIMIT_SOFT_MB * 1024 * 1024
......@@ -95,6 +107,19 @@ def check_project_file(path: Path, force: bool) -> None:
console.print(f"[red]{path.name} is not a valid .zip file.[/]")
raise CheckError
with open(PROJECT_NB_NAME, "r") as f:
nb = nbformat.read(f, as_version=4)
topics_cell = find_nb_tag(nb, "selected-topics")
cross_count = topics_cell["source"].count("- [x]")
if cross_count != PROJECT_TOPIC_COUNT:
console.print(
f":warning: Found {cross_count} selected topics in the "
"'Selected additional topics' cell, but expected exactly "
f"{PROJECT_TOPIC_COUNT}.\n"
"[b]Please make sure to fill out the list properly and submit again.[/b]"
)
@app.command()
def upload_file(
......@@ -129,7 +154,7 @@ def upload_file(
files = {"file": open(notebook, "rb")}
if project:
files["notebook"] = open("project.ipynb", "rb")
files["notebook"] = open(PROJECT_NB_NAME, "rb")
try:
text = "Uploading" if project else "Testing"
......
output: |
Missing selected-topics cell in notebook
💥 Submission failed! (2022-10-12 13:37:00)
exit_code: 1
input:
tests:
error: []
failed: []
passed: []
skipped: []
xfailed: []
xpassed: []
status:
commit: abcdef
output: |
⚠ Found 0 selected topics in the 'Selected additional topics' cell, but expected
exactly 2.
Please make sure to fill out the list properly and submit again.
📫 ✔ Submission successful! (2022-10-12 13:37:00, abcdef)
exit_code: 0
input:
tests:
error: []
failed: []
passed: []
skipped: []
xfailed: []
xpassed: []
status:
commit: abcdef
output: |
⚠ Found 3 selected topics in the 'Selected additional topics' cell, but expected
exactly 2.
Please make sure to fill out the list properly and submit again.
📫 ✔ Submission successful! (2022-10-12 13:37:00, abcdef)
exit_code: 0
......@@ -3,6 +3,8 @@ from __future__ import annotations
import os
import io
import pathlib
import nbformat
import nbformat.v4
import datetime
import zipfile
from typing import Iterator
......@@ -253,13 +255,26 @@ PROJECT_URL = "http://localhost:5000/project"
@pytest.fixture
def project_notebook(tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch) -> None:
def project_notebook(
tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch
) -> pathlib.Path:
cwd_path = tmp_path / "cwd"
cwd_path.mkdir()
monkeypatch.chdir(cwd_path)
nb_path = cwd_path / "project.ipynb"
nb_path.touch()
nb = nbformat.v4.new_notebook()
nb.cells.append(
nbformat.v4.new_markdown_cell(
"- [x] topic 1\n- [x] topic 2",
metadata={"tags": ["selected-topics"]},
)
)
with nb_path.open("w") as f:
nbformat.write(nb, f)
return nb_path
def test_project(
......@@ -268,7 +283,7 @@ def test_project(
httpx_mock: HTTPXMock,
time_machine: TimeMachineFixture,
tmp_path: pathlib.Path,
project_notebook: None,
project_notebook: pathlib.Path,
) -> None:
httpx_mock.add_response(
url=PROJECT_URL, method="POST", json=golden_special["input"]
......@@ -313,7 +328,7 @@ def test_project_size_limit(
monkeypatch: pytest.MonkeyPatch,
hard_limit: bool,
force: bool,
project_notebook: None,
project_notebook: pathlib.Path,
) -> None:
if force and not hard_limit:
httpx_mock.add_response(
......@@ -366,3 +381,59 @@ def test_version(
assert result.exit_code == 0
assert result.stdout == f"taas-client: {__version__}\ntaas server: 1.2.3\n"
def test_project_notebook_no_cells(
runner: Runner,
golden_special: GoldenTestFixture,
time_machine: TimeMachineFixture,
tmp_path: pathlib.Path,
project_notebook: pathlib.Path,
) -> None:
time_machine.move_to(FROZEN_TIME)
project_path = tmp_path / "project.zip"
with zipfile.ZipFile(project_path, "w"):
pass
with project_notebook.open("r") as f:
nb = nbformat.read(f, as_version=4)
del nb.cells[:]
with project_notebook.open("w") as f:
nbformat.write(nb, f)
result = runner.run("--project", str(project_path))
assert result.exit_code == golden_special.out["exit_code"]
assert result.stdout == golden_special.out["output"]
@pytest.mark.parametrize("count", [0, 3])
def test_project_notebook_topic_selection(
runner: Runner,
golden_special: GoldenTestFixture,
httpx_mock: HTTPXMock,
time_machine: TimeMachineFixture,
tmp_path: pathlib.Path,
project_notebook: pathlib.Path,
count: int,
) -> None:
httpx_mock.add_response(
url=PROJECT_URL, method="POST", json=golden_special["input"]
)
time_machine.move_to(FROZEN_TIME)
project_path = tmp_path / "project.zip"
with zipfile.ZipFile(project_path, "w"):
pass
with project_notebook.open("r") as f:
nb = nbformat.read(f, as_version=4)
nb.cells[0]["source"] = "\n".join(["- [x] bla" * count])
with project_notebook.open("w") as f:
nbformat.write(nb, f)
result = runner.run("--project", str(project_path))
assert result.exit_code == golden_special.out["exit_code"]
assert result.stdout == golden_special.out["output"]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment