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

Add size limits for project uploads

parent ea7ab302
No related branches found
No related tags found
No related merge requests found
Pipeline #234851 passed
......@@ -15,6 +15,8 @@ console = Console()
app = typer.Typer()
BASE_URL = "http://localhost:5000"
PROJECT_LIMIT_SOFT_MB = 5
PROJECT_LIMIT_HARD_MB = 50
def version_callback(value: bool) -> None:
......@@ -48,7 +50,41 @@ def check_notebook_file(path: Path, force: bool) -> None:
def check_project_file(path: Path, force: bool) -> None:
pass
size = path.stat().st_size
soft_limit = PROJECT_LIMIT_SOFT_MB * 1024 * 1024
hard_limit = PROJECT_LIMIT_HARD_MB * 1024 * 1024
assert hard_limit > soft_limit
if size > soft_limit:
console.print(
":x: [red]Your project is over the size limit of "
f"{PROJECT_LIMIT_SOFT_MB} MB.[/red]\n\n"
"This doesn't sound like much, but things add up with >100 students and "
"multiple submissions each. For source code, this should be plenty.\n\n"
"[b]Please make sure[/b] your submission does not accidentally contain "
"things like dog pictures/videos or your virtual environment.\n"
)
if size > hard_limit:
console.print(
":bomb: Since your file is also [b]above the hard limit[/] of "
f"{PROJECT_LIMIT_HARD_MB} MB, this error can not be overridden.\n\n"
"[b]Please reduce the file size or contact your instructor.[/]"
)
raise typer.Exit(1)
if not force:
console.print(
f"[grey]You can use [b]!submit --project --force {path.name}[/b] "
"to override this warning and submit anyways.\n"
"Please only do so if absolutely necessary (e.g. shortly before the "
"deadline).[/]\n\n"
"Otherwise, please [b]reduce the file size[/], "
"or [b]contact your instructor[/] if you need assistance."
)
raise typer.Exit(1)
else:
console.print("Continuing submission since --force has been given.\n")
@app.command()
......
input:
tests:
error: []
failed: []
passed: []
skipped: []
xfailed: []
xpassed: []
status:
commit: abcdef
output: |
❌ Your project is over the size limit of 1 MB.
This doesn't sound like much, but things add up with >100 students and multiple
submissions each. For source code, this should be plenty.
Please make sure your submission does not accidentally contain things like dog
pictures/videos or your virtual environment.
💣 Since your file is also above the hard limit of 2 MB, this error can not be
overridden.
Please reduce the file size or contact your instructor.
exit_code: 1
input:
tests:
error: []
failed: []
passed: []
skipped: []
xfailed: []
xpassed: []
status:
commit: abcdef
output: |
❌ Your project is over the size limit of 1 MB.
This doesn't sound like much, but things add up with >100 students and multiple
submissions each. For source code, this should be plenty.
Please make sure your submission does not accidentally contain things like dog
pictures/videos or your virtual environment.
💣 Since your file is also above the hard limit of 2 MB, this error can not be
overridden.
Please reduce the file size or contact your instructor.
exit_code: 1
input:
tests:
error: []
failed: []
passed: []
skipped: []
xfailed: []
xpassed: []
status:
commit: abcdef
output: |
❌ Your project is over the size limit of 1 MB.
This doesn't sound like much, but things add up with >100 students and multiple
submissions each. For source code, this should be plenty.
Please make sure your submission does not accidentally contain things like dog
pictures/videos or your virtual environment.
You can use !submit --project --force project.zip to override this warning and
submit anyways.
Please only do so if absolutely necessary (e.g. shortly before the deadline).
Otherwise, please reduce the file size, or contact your instructor if you need
assistance.
exit_code: 1
input:
tests:
error: []
failed: []
passed: []
skipped: []
xfailed: []
xpassed: []
status:
commit: abcdef
output: |
❌ Your project is over the size limit of 1 MB.
This doesn't sound like much, but things add up with >100 students and multiple
submissions each. For source code, this should be plenty.
Please make sure your submission does not accidentally contain things like dog
pictures/videos or your virtual environment.
Continuing submission since --force has been given.
📫 ✔ Submission successful! (2022-10-12 13:37:00, abcdef)
exit_code: 0
......@@ -236,9 +236,13 @@ def golden_special(
request: pytest.FixtureRequest, golden: GoldenTestFixture
) -> GoldenTestFixture:
name = request.node.name[len("test_") :]
name = name.replace("[", "_").replace("]", "")
return golden.open(GOLDEN_PATH / "special" / f"{name}.yml")
PROJECT_URL = "http://localhost:5000/project"
def test_project(
runner: Runner,
golden_special: GoldenTestFixture,
......@@ -247,11 +251,8 @@ def test_project(
tmp_path: pathlib.Path,
) -> None:
httpx_mock.add_response(
url="http://localhost:5000/project",
method="POST",
json=golden_special["input"],
url=PROJECT_URL, method="POST", json=golden_special["input"]
)
time_machine.move_to(FROZEN_TIME)
project_path = tmp_path / "project.zip"
......@@ -263,6 +264,49 @@ def test_project(
assert result.stdout == golden_special.out["output"]
@pytest.mark.parametrize(
"hard_limit, force",
[
pytest.param(False, False, id="soft"),
pytest.param(False, True, id="soft_force"),
pytest.param(True, False, id="hard"),
pytest.param(True, True, id="hard_force"),
],
)
def test_project_size_limit(
runner: Runner,
golden_special: GoldenTestFixture,
httpx_mock: HTTPXMock,
time_machine: TimeMachineFixture,
tmp_path: pathlib.Path,
monkeypatch: pytest.MonkeyPatch,
hard_limit: bool,
force: bool,
) -> None:
if force and not hard_limit:
httpx_mock.add_response(
url=PROJECT_URL, method="POST", json=golden_special["input"]
)
time_machine.move_to(FROZEN_TIME)
monkeypatch.setattr(cli, "PROJECT_LIMIT_SOFT_MB", 1)
monkeypatch.setattr(cli, "PROJECT_LIMIT_HARD_MB", 2)
file_size_mb = 2 if hard_limit else 1
project_path = tmp_path / "project.zip"
with project_path.open("wb") as f:
f.seek(file_size_mb * 1024 * 1024)
f.write(b"\x00")
flags = ["--project"]
if force:
flags.append("--force")
result = runner.run(*flags, str(project_path))
assert result.exit_code == golden_special.out["exit_code"]
assert result.stdout == golden_special.out["output"]
def test_version(
runner: Runner,
httpx_mock: HTTPXMock,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment