dlai-grader 1.22.2__py3-none-any.whl → 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of dlai-grader might be problematic. Click here for more details.
- dlai_grader/__init__.py +1 -1
- dlai_grader/config.py +12 -5
- dlai_grader/grading.py +58 -30
- dlai_grader/io.py +68 -18
- dlai_grader/notebook.py +10 -10
- dlai_grader/templates/Makefile +57 -0
- dlai_grader/templates/copy_assignment_sh/extrafile_n +12 -0
- dlai_grader/templates/copy_assignment_sh/extrafile_y +16 -0
- dlai_grader/templates/dockerfile/data_n_solution_n +20 -0
- dlai_grader/templates/dockerfile/data_n_solution_y +21 -0
- dlai_grader/templates/dockerfile/data_y_solution_n +21 -0
- dlai_grader/templates/dockerfile/data_y_solution_y +22 -0
- dlai_grader/templates/entry_py/solution_n_file_n.py +76 -0
- dlai_grader/templates/entry_py/solution_n_file_y.py +95 -0
- dlai_grader/templates/entry_py/solution_y_file_n.py +76 -0
- dlai_grader/templates/entry_py/solution_y_file_y.py +95 -0
- dlai_grader/templates/grader.py +31 -0
- dlai_grader/templates.py +244 -205
- dlai_grader/types.py +6 -5
- {dlai_grader-1.22.2.dist-info → dlai_grader-2.0.0.dist-info}/METADATA +10 -5
- dlai_grader-2.0.0.dist-info/RECORD +27 -0
- {dlai_grader-1.22.2.dist-info → dlai_grader-2.0.0.dist-info}/WHEEL +1 -1
- dlai_grader/py.typed +0 -0
- dlai_grader-1.22.2.dist-info/RECORD +0 -16
- {dlai_grader-1.22.2.dist-info → dlai_grader-2.0.0.dist-info}/entry_points.txt +0 -0
- {dlai_grader-1.22.2.dist-info → dlai_grader-2.0.0.dist-info/licenses}/LICENSE +0 -0
- {dlai_grader-1.22.2.dist-info → dlai_grader-2.0.0.dist-info}/top_level.txt +0 -0
dlai_grader/templates.py
CHANGED
|
@@ -1,262 +1,301 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import textwrap
|
|
1
3
|
from textwrap import dedent
|
|
2
|
-
|
|
4
|
+
import shutil
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
3
7
|
|
|
4
8
|
|
|
5
|
-
def
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if week_or_module == "1":
|
|
11
|
-
week = input("Number of the week: ")
|
|
12
|
-
module = None
|
|
13
|
-
elif week_or_module == "2":
|
|
14
|
-
module = input("Number of the module: ")
|
|
15
|
-
week = None
|
|
16
|
-
else:
|
|
17
|
-
print("invalid option selected")
|
|
18
|
-
exit(1)
|
|
19
|
-
|
|
20
|
-
unit_test_filename = input("Filename for unit tests (leave empty for unittests): ")
|
|
21
|
-
unit_test_filename = "unittests" if not unit_test_filename else unit_test_filename
|
|
22
|
-
version = input("Version of the grader (leave empty for version 1): ")
|
|
23
|
-
version = "1" if not version else version
|
|
24
|
-
|
|
25
|
-
dockerfile = """
|
|
26
|
-
FROM continuumio/miniconda3@sha256:d601a04ea48fd45e60808c7072243d33703d29434d2067816b7f26b0705d889a
|
|
27
|
-
|
|
28
|
-
RUN apk update && apk add libstdc++
|
|
29
|
-
|
|
30
|
-
COPY requirements.txt .
|
|
31
|
-
|
|
32
|
-
RUN pip install -r requirements.txt && \
|
|
33
|
-
rm requirements.txt
|
|
34
|
-
|
|
35
|
-
RUN mkdir /grader && \
|
|
36
|
-
mkdir /grader/submission
|
|
37
|
-
|
|
38
|
-
COPY .conf /grader/.conf
|
|
39
|
-
COPY data/ /grader/data/
|
|
40
|
-
COPY solution/ /grader/solution/
|
|
41
|
-
COPY entry.py /grader/entry.py
|
|
42
|
-
COPY grader.py /grader/grader.py
|
|
43
|
-
|
|
44
|
-
RUN chmod a+rwx /grader/
|
|
45
|
-
|
|
46
|
-
WORKDIR /grader/
|
|
47
|
-
|
|
48
|
-
ENTRYPOINT ["python", "entry.py"]
|
|
9
|
+
def generate_copy_assignment_script(
|
|
10
|
+
extra_file_required="n",
|
|
11
|
+
assignment_name="C1M2_Assignment.ipynb",
|
|
12
|
+
extra_file_name="foo.txt",
|
|
13
|
+
):
|
|
49
14
|
"""
|
|
15
|
+
Copy the appropriate copy_assignment_to_submission.sh script from templates depending on whether an extra file is required.
|
|
50
16
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
17
|
+
Template files should be named:
|
|
18
|
+
extrafile_n (no extra file)
|
|
19
|
+
extrafile_y (with extra file)
|
|
54
20
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
W_OR_M_num = module
|
|
21
|
+
Returns:
|
|
22
|
+
str: The final shell script contents after variable substitution.
|
|
58
23
|
|
|
59
|
-
conf = f"""
|
|
60
|
-
ASSIGNMENT_NAME=C{course}{W_OR_M}{W_OR_M_num}_Assignment
|
|
61
|
-
UNIT_TESTS_NAME={unit_test_filename}
|
|
62
|
-
IMAGE_NAME={specialization}c{course}{W_OR_M.lower()}{W_OR_M_num}-grader
|
|
63
|
-
GRADER_VERSION={version}
|
|
64
|
-
TAG_ID=V$(GRADER_VERSION)
|
|
65
|
-
SUB_DIR=mount
|
|
66
|
-
MEMORY_LIMIT=4096
|
|
67
24
|
"""
|
|
25
|
+
if extra_file_required not in ("y", "n"):
|
|
26
|
+
raise ValueError(f"Invalid extra_file_required value: {extra_file_required!r}")
|
|
68
27
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
include .conf
|
|
28
|
+
# Define template name pattern
|
|
29
|
+
template_name = f"extrafile_{extra_file_required}"
|
|
73
30
|
|
|
74
|
-
|
|
75
|
-
|
|
31
|
+
# Paths
|
|
32
|
+
base_dir = Path(__file__).parent
|
|
33
|
+
src = base_dir / "templates" / "copy_assignment_sh" / template_name
|
|
34
|
+
dst = Path("copy_assignment_to_submission.sh")
|
|
76
35
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
cp mount/$(UNIT_TESTS_NAME).py ../$(UNIT_TESTS_NAME).py
|
|
36
|
+
# Validate existence
|
|
37
|
+
if not src.exists():
|
|
38
|
+
raise FileNotFoundError(f"Template not found: {src}")
|
|
81
39
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
40
|
+
# Read and substitute placeholders
|
|
41
|
+
content = src.read_text(encoding="utf-8")
|
|
42
|
+
content = content.replace("{{ASSIGNMENT_NAME}}", assignment_name).replace(
|
|
43
|
+
"{{EXTRA_FILE_NAME}}", extra_file_name
|
|
44
|
+
)
|
|
87
45
|
|
|
88
|
-
|
|
89
|
-
|
|
46
|
+
# Write output
|
|
47
|
+
dst.write_text(content, encoding="utf-8")
|
|
48
|
+
dst.chmod(0o755) # make executable
|
|
49
|
+
return content
|
|
90
50
|
|
|
91
|
-
submit-solution:
|
|
92
|
-
cp solution/solution.ipynb mount/submission.ipynb
|
|
93
51
|
|
|
94
|
-
|
|
95
|
-
|
|
52
|
+
def copy_entry_script(
|
|
53
|
+
sol_dir_required: str,
|
|
54
|
+
non_notebook_grading: str,
|
|
55
|
+
extra_file_name="foo.txt",
|
|
56
|
+
) -> str:
|
|
57
|
+
# Validate inputs
|
|
58
|
+
if sol_dir_required not in ("y", "n"):
|
|
59
|
+
raise ValueError(f"Invalid sol_dir_required value: {sol_dir_required!r}")
|
|
60
|
+
if non_notebook_grading not in ("y", "n"):
|
|
61
|
+
raise ValueError(
|
|
62
|
+
f"Invalid non_notebook_grading value: {non_notebook_grading!r}"
|
|
63
|
+
)
|
|
96
64
|
|
|
97
|
-
|
|
98
|
-
dlai_grader --tag
|
|
65
|
+
template_name = f"solution_{sol_dir_required}_file_{non_notebook_grading}.py"
|
|
99
66
|
|
|
100
|
-
|
|
101
|
-
|
|
67
|
+
base_dir = Path(__file__).parent
|
|
68
|
+
src = base_dir / "templates" / "entry_py" / template_name
|
|
69
|
+
content = src.read_text(encoding="utf-8")
|
|
70
|
+
content = content.replace("{{EXTRA_FILE_NAME}}", extra_file_name)
|
|
71
|
+
dst = Path("entry.py")
|
|
102
72
|
|
|
103
|
-
|
|
104
|
-
|
|
73
|
+
if not src.exists():
|
|
74
|
+
raise FileNotFoundError(f"Template not found: {src}")
|
|
105
75
|
|
|
106
|
-
|
|
107
|
-
|
|
76
|
+
# shutil.copy(src, dst)
|
|
77
|
+
return content
|
|
108
78
|
|
|
109
|
-
test:
|
|
110
|
-
docker run -it --rm --mount type=bind,source=$(PWD)/mount,target=/shared/submission --mount type=bind,source=$(PWD),target=/grader/ --entrypoint pytest $(IMAGE_NAME):$(TAG_ID)
|
|
111
79
|
|
|
112
|
-
|
|
113
|
-
|
|
80
|
+
def generate_dockerfile(data_dir_required="n", sol_dir_required="n"):
|
|
81
|
+
"""
|
|
82
|
+
Generate a Dockerfile with optional data and solution directories.
|
|
114
83
|
|
|
115
|
-
|
|
116
|
-
|
|
84
|
+
Args:
|
|
85
|
+
data_dir_required (str): Include data directory if "y"
|
|
86
|
+
sol_dir_required (str): Include solution directory if "y"
|
|
117
87
|
|
|
118
|
-
|
|
119
|
-
|
|
88
|
+
"""
|
|
89
|
+
# Validate inputs
|
|
90
|
+
if data_dir_required not in ("y", "n"):
|
|
91
|
+
raise ValueError(f"Invalid data_dir_required value: {data_dir_required!r}")
|
|
92
|
+
if sol_dir_required not in ("y", "n"):
|
|
93
|
+
raise ValueError(f"Invalid sol_dir_required value: {sol_dir_required!r}")
|
|
120
94
|
|
|
121
|
-
|
|
122
|
-
find . -maxdepth 1 -type f -name "*.zip" -exec rm {} +
|
|
123
|
-
docker rm $$(docker ps -qa --no-trunc --filter "status=exited")
|
|
124
|
-
docker rmi $$(docker images --filter "dangling=true" -q --no-trunc)
|
|
95
|
+
template_name = f"data_{data_dir_required}_solution_{sol_dir_required}"
|
|
125
96
|
|
|
126
|
-
|
|
127
|
-
|
|
97
|
+
# Define paths
|
|
98
|
+
base_dir = Path(__file__).parent
|
|
99
|
+
src = base_dir / "templates" / "dockerfile" / template_name
|
|
100
|
+
dst = Path("Dockerfile")
|
|
128
101
|
|
|
129
|
-
|
|
102
|
+
# Ensure the source exists
|
|
103
|
+
if not src.exists():
|
|
104
|
+
raise FileNotFoundError(f"Template not found: {src}")
|
|
130
105
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
from typing import Dict, List, Optional
|
|
134
|
-
from dlai_grader.grading import test_case, object_to_grade
|
|
135
|
-
from dlai_grader.types import grading_function, grading_wrapper, learner_submission
|
|
106
|
+
# Copy template to current directory
|
|
107
|
+
# shutil.copy(src, dst)
|
|
136
108
|
|
|
109
|
+
# Return the Dockerfile contents
|
|
110
|
+
return src.read_text(encoding="utf-8")
|
|
137
111
|
|
|
138
|
-
def part_1(
|
|
139
|
-
learner_mod: learner_submission, solution_mod: Optional[ModuleType] = None
|
|
140
|
-
) -> grading_function:
|
|
141
|
-
@object_to_grade(learner_mod, "learner_func")
|
|
142
|
-
def g(learner_func: FunctionType) -> List[test_case]:
|
|
143
112
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
113
|
+
def copy_makefile() -> str:
|
|
114
|
+
base_dir = Path(__file__).parent
|
|
115
|
+
src = base_dir / "templates" / "Makefile"
|
|
116
|
+
# content = src.read_text(encoding="utf-8")
|
|
117
|
+
# content = content.replace("{{HARD_MEMORY}}", hard_memory)
|
|
118
|
+
# content = content.replace("{{CPUS}}", cpus)
|
|
119
|
+
# content = content.replace("{{SOFT_MEMORY}}", soft_memory)
|
|
120
|
+
dst = Path("Makefile")
|
|
151
121
|
|
|
152
|
-
|
|
122
|
+
if not src.exists():
|
|
123
|
+
raise FileNotFoundError(f"Template not found: {src}")
|
|
153
124
|
|
|
154
|
-
|
|
125
|
+
# shutil.copy(src, dst)
|
|
126
|
+
return src.read_text(encoding="utf-8")
|
|
155
127
|
|
|
156
|
-
return g
|
|
157
128
|
|
|
129
|
+
def copy_grader_py() -> str:
|
|
130
|
+
base_dir = Path(__file__).parent
|
|
131
|
+
src = base_dir / "templates" / "grader.py"
|
|
132
|
+
dst = Path("grader.py")
|
|
158
133
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
"": part_1,
|
|
162
|
-
}
|
|
163
|
-
return grader_dict[part_id]
|
|
164
|
-
"""
|
|
134
|
+
if not src.exists():
|
|
135
|
+
raise FileNotFoundError(f"Template not found: {src}")
|
|
165
136
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
from dlai_grader.compiler import compile_partial_module
|
|
169
|
-
from dlai_grader.io import read_notebook, copy_submission_to_workdir, send_feedback
|
|
170
|
-
|
|
171
|
-
from dlai_grader.notebook import (
|
|
172
|
-
notebook_to_script,
|
|
173
|
-
keep_tagged_cells,
|
|
174
|
-
notebook_is_up_to_date,
|
|
175
|
-
notebook_version,
|
|
176
|
-
cut_notebook,
|
|
177
|
-
partial_grading_enabled,
|
|
178
|
-
)
|
|
179
|
-
from dlai_grader.grading import compute_grading_score, graded_obj_missing
|
|
180
|
-
from grader import handle_part_id
|
|
137
|
+
# shutil.copy(src, dst)
|
|
138
|
+
return src.read_text(encoding="utf-8")
|
|
181
139
|
|
|
182
140
|
|
|
183
|
-
|
|
184
|
-
|
|
141
|
+
def load_templates() -> dict[str, str]:
|
|
142
|
+
specialization = input("Name of the specialization: ")
|
|
143
|
+
course = input("Number of the course: ")
|
|
144
|
+
module = input("Number of the module: ")
|
|
185
145
|
|
|
186
|
-
|
|
146
|
+
grader_mvp = input(
|
|
147
|
+
"Use minimum grader (no extra config)? y/n (leave empty for n): ",
|
|
148
|
+
)
|
|
187
149
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
150
|
+
grader_mvp = grader_mvp if grader_mvp else "n"
|
|
151
|
+
if grader_mvp not in ["y", "n"]:
|
|
152
|
+
print("invalid option selected")
|
|
153
|
+
sys.exit(1)
|
|
154
|
+
|
|
155
|
+
if grader_mvp == "n":
|
|
156
|
+
unit_test_filename = input(
|
|
157
|
+
"Filename for unit tests (leave empty for unittests): "
|
|
158
|
+
)
|
|
159
|
+
unit_test_filename = unit_test_filename if unit_test_filename else "unittests"
|
|
160
|
+
# version = input("Version of the grader (leave empty for version 1): ")
|
|
161
|
+
version = "1"
|
|
162
|
+
|
|
163
|
+
data_dir_required = ""
|
|
164
|
+
while data_dir_required not in ["y", "n"]:
|
|
165
|
+
data_dir_required = input(
|
|
166
|
+
"Do you require a data dir? y/n (leave empty for n): ",
|
|
195
167
|
)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
for t in transformations:
|
|
205
|
-
nb = t(nb)
|
|
206
|
-
|
|
207
|
-
try:
|
|
208
|
-
learner_mod = compile_partial_module(nb, "learner_mod", verbose=False)
|
|
209
|
-
except Exception as e:
|
|
210
|
-
send_feedback(
|
|
211
|
-
0.0,
|
|
212
|
-
f"There was a problem compiling the code from your notebook, please check that you saved before submitting. Details:\\n{str(e)}",
|
|
213
|
-
err=True,
|
|
168
|
+
if data_dir_required == "":
|
|
169
|
+
data_dir_required = "n"
|
|
170
|
+
# data_dir_required = data_dir_required if data_dir_required else "n"
|
|
171
|
+
|
|
172
|
+
sol_dir_required = ""
|
|
173
|
+
while sol_dir_required not in ["y", "n"]:
|
|
174
|
+
sol_dir_required = input(
|
|
175
|
+
"Do you require a solution file? y/n (leave empty for n): ",
|
|
214
176
|
)
|
|
177
|
+
if sol_dir_required == "":
|
|
178
|
+
sol_dir_required = "n"
|
|
215
179
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
g_func = handle_part_id(c.part_id)(learner_mod)
|
|
180
|
+
non_notebook_grading = ""
|
|
181
|
+
while non_notebook_grading not in ["y", "n"]:
|
|
182
|
+
non_notebook_grading = input(
|
|
183
|
+
"Will you grade a file different from a notebook? y/n (leave empty for n): ",
|
|
184
|
+
)
|
|
185
|
+
if non_notebook_grading == "":
|
|
186
|
+
non_notebook_grading = "n"
|
|
224
187
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
0.0,
|
|
230
|
-
f"There was an error grading your submission. Details:\\n{str(e)}",
|
|
231
|
-
err=True,
|
|
188
|
+
extra_file_name = ""
|
|
189
|
+
if non_notebook_grading == "y":
|
|
190
|
+
extra_file_name = input(
|
|
191
|
+
"Name of the extra file to grade: ",
|
|
232
192
|
)
|
|
233
193
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
194
|
+
cpus = ""
|
|
195
|
+
while cpus not in ["0.25", "0.5", "0.75", "1"]:
|
|
196
|
+
cpus = input("CPU Units (leave empty for 0.25): ")
|
|
197
|
+
if cpus == "":
|
|
198
|
+
cpus = "0.25"
|
|
199
|
+
|
|
200
|
+
if cpus not in ["0.25", "0.5", "0.75", "1"]:
|
|
201
|
+
print(f"Options are: {['0.25', '0.5', '0.75', '1']}")
|
|
202
|
+
|
|
203
|
+
soft_memory = ""
|
|
204
|
+
soft_memory_options = [
|
|
205
|
+
"512m",
|
|
206
|
+
"768m",
|
|
207
|
+
"1024m",
|
|
208
|
+
"2048m",
|
|
209
|
+
"4096m",
|
|
210
|
+
"8192m",
|
|
211
|
+
"1g",
|
|
212
|
+
"2g",
|
|
213
|
+
"4g",
|
|
214
|
+
"8g",
|
|
215
|
+
]
|
|
216
|
+
while soft_memory not in soft_memory_options:
|
|
217
|
+
soft_memory = input("Memory Reservation (leave empty for 512m): ")
|
|
218
|
+
if soft_memory == "":
|
|
219
|
+
soft_memory = "512m"
|
|
220
|
+
|
|
221
|
+
if soft_memory not in soft_memory_options:
|
|
222
|
+
print(f"Options are: {soft_memory_options}")
|
|
223
|
+
|
|
224
|
+
hard_memory = ""
|
|
225
|
+
hard_memory_options = [
|
|
226
|
+
"1024m",
|
|
227
|
+
"2048m",
|
|
228
|
+
"4096m",
|
|
229
|
+
"8192m",
|
|
230
|
+
"15000m",
|
|
231
|
+
"1g",
|
|
232
|
+
"2g",
|
|
233
|
+
"4g",
|
|
234
|
+
"8g",
|
|
235
|
+
"15g",
|
|
236
|
+
]
|
|
237
|
+
while hard_memory not in hard_memory_options:
|
|
238
|
+
hard_memory = input("Memory Limit (leave empty for 1g): ")
|
|
239
|
+
if hard_memory == "":
|
|
240
|
+
hard_memory = "1g"
|
|
241
|
+
|
|
242
|
+
if hard_memory not in hard_memory_options:
|
|
243
|
+
print(f"Options are: {hard_memory_options}")
|
|
244
|
+
|
|
245
|
+
if grader_mvp == "y":
|
|
246
|
+
unit_test_filename = "unittests"
|
|
247
|
+
version = "1"
|
|
248
|
+
data_dir_required = "n"
|
|
249
|
+
sol_dir_required = "n"
|
|
250
|
+
non_notebook_grading = "n"
|
|
251
|
+
extra_file_name = ""
|
|
252
|
+
cpus = "0.25"
|
|
253
|
+
soft_memory = "512m"
|
|
254
|
+
hard_memory = "1g"
|
|
255
|
+
|
|
256
|
+
dockerfile = generate_dockerfile(
|
|
257
|
+
data_dir_required=data_dir_required,
|
|
258
|
+
sol_dir_required=sol_dir_required,
|
|
259
|
+
)
|
|
238
260
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
261
|
+
conf = f"""
|
|
262
|
+
ASSIGNMENT_NAME=C{course}M{module}_Assignment
|
|
263
|
+
UNIT_TESTS_NAME={unit_test_filename}
|
|
264
|
+
IMAGE_NAME={specialization}c{course}m{module}-grader
|
|
265
|
+
GRADER_VERSION={version}
|
|
266
|
+
TAG_ID=V$(GRADER_VERSION)
|
|
267
|
+
SUB_DIR=mount
|
|
268
|
+
MEMORY_LIMIT=4096
|
|
269
|
+
CPUS={cpus}
|
|
270
|
+
SOFT_MEMORY={soft_memory}
|
|
271
|
+
HARD_MEMORY={hard_memory}
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
assignment_name = f"C{course}M{module}_Assignment.ipynb"
|
|
244
275
|
|
|
245
|
-
|
|
276
|
+
copy_assignment_to_submission_sh = generate_copy_assignment_script(
|
|
277
|
+
extra_file_required=non_notebook_grading,
|
|
278
|
+
assignment_name=assignment_name,
|
|
279
|
+
extra_file_name=extra_file_name,
|
|
280
|
+
)
|
|
246
281
|
|
|
247
|
-
|
|
282
|
+
makefile = copy_makefile()
|
|
248
283
|
|
|
284
|
+
grader_py = copy_grader_py()
|
|
249
285
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
286
|
+
entry_py = copy_entry_script(
|
|
287
|
+
sol_dir_required=sol_dir_required,
|
|
288
|
+
non_notebook_grading=non_notebook_grading,
|
|
289
|
+
extra_file_name=extra_file_name,
|
|
290
|
+
)
|
|
253
291
|
|
|
254
292
|
template_dict = {
|
|
255
|
-
"dockerfile": dedent(dockerfile
|
|
256
|
-
"makefile": dedent(makefile
|
|
293
|
+
"dockerfile": dedent(dockerfile),
|
|
294
|
+
"makefile": dedent(makefile),
|
|
257
295
|
"conf": dedent(conf[1:]),
|
|
258
|
-
"grader_py": dedent(grader_py
|
|
259
|
-
"entry_py": dedent(entry_py
|
|
296
|
+
"grader_py": dedent(grader_py),
|
|
297
|
+
"entry_py": dedent(entry_py),
|
|
298
|
+
# "copy_assignment_to_submission_sh": dedent(copy_assignment_to_submission_sh),
|
|
260
299
|
}
|
|
261
300
|
|
|
262
301
|
return template_dict
|
dlai_grader/types.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
1
2
|
from types import ModuleType
|
|
2
|
-
from typing import Any, Callable, List, Optional, Union
|
|
3
|
-
from .grading import test_case, LearnerSubmission
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
from .grading import LearnerSubmission, test_case
|
|
5
|
+
|
|
6
|
+
grading_function = Callable[..., list[test_case]]
|
|
7
|
+
learner_submission = ModuleType | LearnerSubmission
|
|
8
|
+
grading_wrapper = Callable[[learner_submission, ModuleType | None], grading_function]
|
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: dlai-grader
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Grading utilities for DLAI courses
|
|
5
5
|
Home-page: https://github.com/https-deeplearning-ai/grader
|
|
6
6
|
Author: Andres Zarta
|
|
7
|
-
Author-email: andrezb5@gmail.com
|
|
7
|
+
Author-email: Andres Zarta <andrezb5@gmail.com>
|
|
8
8
|
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/https-deeplearning-ai/grader
|
|
9
10
|
Classifier: Programming Language :: Python :: 3
|
|
10
11
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
12
|
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.10
|
|
12
14
|
Description-Content-Type: text/markdown
|
|
13
15
|
License-File: LICENSE
|
|
14
|
-
Requires-Dist: nbformat
|
|
15
|
-
Requires-Dist: jupytext
|
|
16
|
+
Requires-Dist: nbformat>=5.1.3
|
|
17
|
+
Requires-Dist: jupytext>=1.13.0
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: home-page
|
|
20
|
+
Dynamic: license-file
|
|
16
21
|
|
|
17
22
|
# grader
|
|
18
23
|
Automatic grading for DLAI courses. Designed to be compatible with Coursera's grading requirements.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
dlai_grader/__init__.py,sha256=l75TgaacUAl8VICMFLF_epE-k-sXbqoynTo4rISqDU4,210
|
|
2
|
+
dlai_grader/cli.py,sha256=NIwboE-AFn1LXOFmF4O70Ow0fkRxgclG_eMwmWiua38,4917
|
|
3
|
+
dlai_grader/compiler.py,sha256=elbHNUCqBCoOOoNmMRXbgeNL0nt0RM57eZi0-6AqycA,3036
|
|
4
|
+
dlai_grader/config.py,sha256=DokK1tVF_r7v0p9tWpBN-7lOAlPmHSpFXDZiI8cGw7s,1821
|
|
5
|
+
dlai_grader/grading.py,sha256=BMIoZ_loQDuNCEk1Dj3on4IWz-FGgIbnhbDyk8HmQ7c,5041
|
|
6
|
+
dlai_grader/io.py,sha256=5hs7Bv5zfyHKZUrFP-2gVH7y9dbIFsyGiKgsqFYbrMs,9250
|
|
7
|
+
dlai_grader/notebook.py,sha256=MgxZFuetTXwwZ-HXSB5ItLVD_9LP45E0xHAngS0g4EU,12101
|
|
8
|
+
dlai_grader/templates.py,sha256=OdmwnmNS2KCCcZ4-9jqfclV43tmbJoSuCk-5QWU6KoE,9291
|
|
9
|
+
dlai_grader/types.py,sha256=5uiFaF3aDn-vjxTp9ec-ND-PRqeeV2_NfPHS2ngGsRo,306
|
|
10
|
+
dlai_grader/templates/Makefile,sha256=hQLhl-xLGw5WmACjlSGxlXA0Bc13XOY_4i5RaAunWlU,1904
|
|
11
|
+
dlai_grader/templates/grader.py,sha256=AeazA3RzXTmplAwsFuDR9XKOluRj-EJSkhMLzJFGioo,899
|
|
12
|
+
dlai_grader/templates/copy_assignment_sh/extrafile_n,sha256=qB9ZViBm69r69nT9WXDaJfrW57sVho03aCZXbTS-lTc,430
|
|
13
|
+
dlai_grader/templates/copy_assignment_sh/extrafile_y,sha256=Zh07IAViyN-rELp4_-ZOJJSmTIigh0GxHLexW0ZGnMQ,616
|
|
14
|
+
dlai_grader/templates/dockerfile/data_n_solution_n,sha256=mD_fHhkzrGCCG3EPwXmafYVn1AoIcgBmSZLX8eCeH_g,447
|
|
15
|
+
dlai_grader/templates/dockerfile/data_n_solution_y,sha256=9iSyDj3-Jwm6RyAHNtVUDeD-XrYODB61i-HB3HfA70g,480
|
|
16
|
+
dlai_grader/templates/dockerfile/data_y_solution_n,sha256=i9nWcTAUCQzyhx3kM1aH64j0dkEMlYlEb6FFiE5k5oc,472
|
|
17
|
+
dlai_grader/templates/dockerfile/data_y_solution_y,sha256=xs6p-puJ-j5AeIuHiESL7X9kNSFZVCZ3Wb9SAW9KlUU,505
|
|
18
|
+
dlai_grader/templates/entry_py/solution_n_file_n.py,sha256=hZr5pcijXi-LOrJCInjEiiux5afIZXwhamdz_QjWCW0,2354
|
|
19
|
+
dlai_grader/templates/entry_py/solution_n_file_y.py,sha256=9X5ynsGDGRrrre-noXA7y6g4TgvZBBi5tKL0cDJ7xaA,2989
|
|
20
|
+
dlai_grader/templates/entry_py/solution_y_file_n.py,sha256=ejRspmifrha0qY3WWUcHmbDQB86jXDpj6hdt-VFmntA,2402
|
|
21
|
+
dlai_grader/templates/entry_py/solution_y_file_y.py,sha256=hpbuRjQLhw5ugbBtaOm6oKqk8lrKxRhPz0Tg2On13ws,3057
|
|
22
|
+
dlai_grader-2.0.0.dist-info/licenses/LICENSE,sha256=a_kch_UqdJPtyxk35QJr9O84K_koPixqWPYW9On4-io,1072
|
|
23
|
+
dlai_grader-2.0.0.dist-info/METADATA,sha256=ki7k6bXCR5BsJnARXk1r5gwaU0d3SPm3uFmv12a3juU,8776
|
|
24
|
+
dlai_grader-2.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
25
|
+
dlai_grader-2.0.0.dist-info/entry_points.txt,sha256=4OcSAUIluONXa3ymViQ7CBQ2Lk52nb6xZnfph1rlMnk,71
|
|
26
|
+
dlai_grader-2.0.0.dist-info/top_level.txt,sha256=4YKtA3ztisFtx_g4hsGivy3J2NHnXxFziIMqawC8HWg,12
|
|
27
|
+
dlai_grader-2.0.0.dist-info/RECORD,,
|
dlai_grader/py.typed
DELETED
|
File without changes
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
dlai_grader/__init__.py,sha256=NJssrhk1f1ZuaTeZOoOhn2cgxdwJV9v6bXD-7WdoS7M,211
|
|
2
|
-
dlai_grader/cli.py,sha256=NIwboE-AFn1LXOFmF4O70Ow0fkRxgclG_eMwmWiua38,4917
|
|
3
|
-
dlai_grader/compiler.py,sha256=elbHNUCqBCoOOoNmMRXbgeNL0nt0RM57eZi0-6AqycA,3036
|
|
4
|
-
dlai_grader/config.py,sha256=HQ3dzaFpRswIA_7EC8XdP8DdJH-XePsbMQMHG8Esblc,1638
|
|
5
|
-
dlai_grader/grading.py,sha256=Gmft9b7M8At_y_WZDatYdW6tinZMfqQoT7bDXp6uz2I,4606
|
|
6
|
-
dlai_grader/io.py,sha256=HybOy-0aPbJfxzQDjYOE2qo1myXKt0rlX90fzV1PXJo,8264
|
|
7
|
-
dlai_grader/notebook.py,sha256=66-08JUF5l5AS3UETYyTOn0mDjSPJtEetP7guiz4cYQ,12125
|
|
8
|
-
dlai_grader/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
dlai_grader/templates.py,sha256=u4BrPuDKefiyjKovxHPF0MbG73FvUIkLhgGpEWRYpL8,7843
|
|
10
|
-
dlai_grader/types.py,sha256=_IIVbYL9cMmwA6in0aI5fEWCIaAMNcQbxG64X1P1CkE,335
|
|
11
|
-
dlai_grader-1.22.2.dist-info/LICENSE,sha256=a_kch_UqdJPtyxk35QJr9O84K_koPixqWPYW9On4-io,1072
|
|
12
|
-
dlai_grader-1.22.2.dist-info/METADATA,sha256=oQls7F3kEzBalJF1ao-tP5cvRaLOk_lD0VXA6lXyalc,8612
|
|
13
|
-
dlai_grader-1.22.2.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
|
14
|
-
dlai_grader-1.22.2.dist-info/entry_points.txt,sha256=4OcSAUIluONXa3ymViQ7CBQ2Lk52nb6xZnfph1rlMnk,71
|
|
15
|
-
dlai_grader-1.22.2.dist-info/top_level.txt,sha256=4YKtA3ztisFtx_g4hsGivy3J2NHnXxFziIMqawC8HWg,12
|
|
16
|
-
dlai_grader-1.22.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|