forked from ucbds-infra/otter-grader
/
__init__.py
78 lines (64 loc) · 2.66 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""Local grading of submissions in Docker containers for Otter-Grader"""
import os
import pandas as pd
import re
from .containers import launch_grade
from .utils import merge_csv, prune_images
from ..utils import assert_path_exists
def main(*, path="./", output_dir="./", autograder="./autograder.zip", containers=None,
scripts=False, no_kill=False, debug=False, zips=False, image="ucbdsinfra/otter-grader",
pdfs=False, verbose=False, prune=False, force=False):
"""
Runs Otter Grade
Grades a directory of submissions in parallel Docker containers. Results are outputted as a CSV file
called ``final_grades.csv``. If ``prune`` is ``True``, Otter's dangling grading images are pruned
and the program exits.
Args:
path (``str``): path to directory of submissions
output_dir (``str``): directory in which to write ``final_grades.csv``
autograder (``str``): path to Otter autograder configuration zip file
containers (``int``): number of containers to run in parallel
scripts (``bool``): whether Python scripts are being graded
no_kill (``bool``): whether to keep containers after grading is finished
debug (``bool``): whether to print the stdout of each container
zips (``bool``): whether the submissions are Otter-exported zip files
image (``bool``): base image from which to build grading image
pdfs (``bool``): whether to copy notebook PDFs out of the containers
verbose (``bool``): whether to log status messages to stdout
prune (``bool``): whether to prune the grading images; if true, no grading is performed
force (``bool``): whether to force-prune the images (do not ask for confirmation)
Raises:
``AssertionError``: if invalid arguments are provided
"""
if prune:
prune_images(force=force)
return
# check file paths
assert_path_exists([
(path, True),
(output_dir, True),
(autograder, False),
])
if verbose:
print("Launching docker containers...")
#Docker
grade_dfs = launch_grade(autograder,
notebooks_dir=path,
verbose=verbose,
num_containers=containers,
scripts=scripts,
no_kill=no_kill,
output_path=output_dir,
debug=debug,
zips=zips,
image=image,
pdfs=pdfs
)
if verbose:
print("Combining grades and saving...")
# Merge Dataframes
output_df = merge_csv(grade_dfs)
cols = output_df.columns.tolist()
output_df = output_df[cols[-1:] + cols[:-1]]
# write to CSV file
output_df.to_csv(os.path.join(output_dir, "final_grades.csv"), index=False)