dlai-grader 1.22.2__py3-none-any.whl → 2.0b2__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 +54 -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 +71 -0
- dlai_grader/templates/entry_py/solution_n_file_y.py +90 -0
- dlai_grader/templates/entry_py/solution_y_file_n.py +71 -0
- dlai_grader/templates/entry_py/solution_y_file_y.py +90 -0
- dlai_grader/templates/grader.py +32 -0
- dlai_grader/templates.py +238 -208
- dlai_grader/types.py +6 -5
- {dlai_grader-1.22.2.dist-info → dlai_grader-2.0b2.dist-info}/METADATA +10 -5
- dlai_grader-2.0b2.dist-info/RECORD +27 -0
- {dlai_grader-1.22.2.dist-info → dlai_grader-2.0b2.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.0b2.dist-info}/entry_points.txt +0 -0
- {dlai_grader-1.22.2.dist-info → dlai_grader-2.0b2.dist-info/licenses}/LICENSE +0 -0
- {dlai_grader-1.22.2.dist-info → dlai_grader-2.0b2.dist-info}/top_level.txt +0 -0
dlai_grader/templates.py
CHANGED
|
@@ -1,262 +1,292 @@
|
|
|
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
|
|
73
|
-
|
|
74
|
-
PARTIDS = ""
|
|
75
|
-
OS := $(shell uname)
|
|
76
|
-
|
|
77
|
-
sync:
|
|
78
|
-
cp mount/submission.ipynb ../$(ASSIGNMENT_NAME)_Solution.ipynb
|
|
79
|
-
cp learner/$(ASSIGNMENT_NAME).ipynb ../$(ASSIGNMENT_NAME).ipynb
|
|
80
|
-
cp mount/$(UNIT_TESTS_NAME).py ../$(UNIT_TESTS_NAME).py
|
|
81
|
-
|
|
82
|
-
learner:
|
|
83
|
-
dlai_grader --learner --output_notebook=./learner/$(ASSIGNMENT_NAME).ipynb
|
|
84
|
-
|
|
85
|
-
build:
|
|
86
|
-
docker build -t $(IMAGE_NAME):$(TAG_ID) .
|
|
87
|
-
|
|
88
|
-
debug:
|
|
89
|
-
docker run -it --rm --mount type=bind,source=$(PWD)/mount,target=/shared/submission --mount type=bind,source=$(PWD),target=/grader/ --entrypoint ash $(IMAGE_NAME):$(TAG_ID)
|
|
90
|
-
|
|
91
|
-
submit-solution:
|
|
92
|
-
cp solution/solution.ipynb mount/submission.ipynb
|
|
28
|
+
# Define template name pattern
|
|
29
|
+
template_name = f"extrafile_{extra_file_required}"
|
|
93
30
|
|
|
94
|
-
|
|
95
|
-
|
|
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")
|
|
96
35
|
|
|
97
|
-
|
|
98
|
-
|
|
36
|
+
# Validate existence
|
|
37
|
+
if not src.exists():
|
|
38
|
+
raise FileNotFoundError(f"Template not found: {src}")
|
|
99
39
|
|
|
100
|
-
|
|
101
|
-
|
|
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
|
+
)
|
|
102
45
|
|
|
103
|
-
|
|
104
|
-
|
|
46
|
+
# Write output
|
|
47
|
+
dst.write_text(content, encoding="utf-8")
|
|
48
|
+
dst.chmod(0o755) # make executable
|
|
49
|
+
return content
|
|
105
50
|
|
|
106
|
-
upgrade:
|
|
107
|
-
dlai_grader --upgrade
|
|
108
51
|
|
|
109
|
-
|
|
110
|
-
|
|
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
|
+
)
|
|
111
64
|
|
|
112
|
-
|
|
113
|
-
dlai_grader --grade --partids=$(PARTIDS) --docker=$(IMAGE_NAME):$(TAG_ID) --memory=$(MEMORY_LIMIT) --submission=$(SUB_DIR)
|
|
65
|
+
template_name = f"solution_{sol_dir_required}_file_{non_notebook_grading}.py"
|
|
114
66
|
|
|
115
|
-
|
|
116
|
-
|
|
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")
|
|
117
72
|
|
|
118
|
-
|
|
119
|
-
|
|
73
|
+
if not src.exists():
|
|
74
|
+
raise FileNotFoundError(f"Template not found: {src}")
|
|
120
75
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
docker rm $$(docker ps -qa --no-trunc --filter "status=exited")
|
|
124
|
-
docker rmi $$(docker images --filter "dangling=true" -q --no-trunc)
|
|
76
|
+
# shutil.copy(src, dst)
|
|
77
|
+
return content
|
|
125
78
|
|
|
126
|
-
upload:
|
|
127
|
-
coursera_autograder --timeout 1800 upload --grader-memory-limit $(MEMORY_LIMIT) --grading-timeout 1800 $(IMAGE_NAME)$(TAG_ID).zip $(COURSE_ID) $(ITEM_ID) $(PART_ID)
|
|
128
79
|
|
|
129
|
-
|
|
80
|
+
def generate_dockerfile(data_dir_required="n", sol_dir_required="n"):
|
|
81
|
+
"""
|
|
82
|
+
Generate a Dockerfile with optional data and solution directories.
|
|
130
83
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
from dlai_grader.grading import test_case, object_to_grade
|
|
135
|
-
from dlai_grader.types import grading_function, grading_wrapper, learner_submission
|
|
84
|
+
Args:
|
|
85
|
+
data_dir_required (str): Include data directory if "y"
|
|
86
|
+
sol_dir_required (str): Include solution directory if "y"
|
|
136
87
|
|
|
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}")
|
|
137
94
|
|
|
138
|
-
|
|
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]:
|
|
95
|
+
template_name = f"data_{data_dir_required}_solution_{sol_dir_required}"
|
|
143
96
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
t.want = FunctionType
|
|
149
|
-
t.got = type(learner_func)
|
|
150
|
-
return [t]
|
|
97
|
+
# Define paths
|
|
98
|
+
base_dir = Path(__file__).parent
|
|
99
|
+
src = base_dir / "templates" / "dockerfile" / template_name
|
|
100
|
+
dst = Path("Dockerfile")
|
|
151
101
|
|
|
152
|
-
|
|
102
|
+
# Ensure the source exists
|
|
103
|
+
if not src.exists():
|
|
104
|
+
raise FileNotFoundError(f"Template not found: {src}")
|
|
153
105
|
|
|
154
|
-
|
|
106
|
+
# Copy template to current directory
|
|
107
|
+
# shutil.copy(src, dst)
|
|
155
108
|
|
|
156
|
-
|
|
109
|
+
# Return the Dockerfile contents
|
|
110
|
+
return src.read_text(encoding="utf-8")
|
|
157
111
|
|
|
158
112
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
""
|
|
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")
|
|
165
121
|
|
|
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
|
|
122
|
+
if not src.exists():
|
|
123
|
+
raise FileNotFoundError(f"Template not found: {src}")
|
|
181
124
|
|
|
125
|
+
# shutil.copy(src, dst)
|
|
126
|
+
return src.read_text(encoding="utf-8")
|
|
182
127
|
|
|
183
|
-
def main() -> None:
|
|
184
|
-
c = Config()
|
|
185
128
|
|
|
186
|
-
|
|
129
|
+
def copy_grader_py() -> str:
|
|
130
|
+
base_dir = Path(__file__).parent
|
|
131
|
+
src = base_dir / "templates" / "grader.py"
|
|
132
|
+
dst = Path("grader.py")
|
|
187
133
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
except Exception as e:
|
|
191
|
-
send_feedback(
|
|
192
|
-
0.0,
|
|
193
|
-
f"There was a problem reading your notebook. Details:\\n{str(e)}",
|
|
194
|
-
err=True,
|
|
195
|
-
)
|
|
134
|
+
if not src.exists():
|
|
135
|
+
raise FileNotFoundError(f"Template not found: {src}")
|
|
196
136
|
|
|
197
|
-
|
|
198
|
-
|
|
137
|
+
# shutil.copy(src, dst)
|
|
138
|
+
return src.read_text(encoding="utf-8")
|
|
199
139
|
|
|
200
|
-
send_feedback(0.0, msg)
|
|
201
140
|
|
|
202
|
-
|
|
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: ")
|
|
203
145
|
|
|
204
|
-
|
|
205
|
-
|
|
146
|
+
grader_mvp = input(
|
|
147
|
+
"Use minimum grader (no extra config)? y/n (leave empty for n): ",
|
|
148
|
+
)
|
|
206
149
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
+
data_dir_required = input(
|
|
163
|
+
"Do you require a data dir? y/n (leave empty for n): "
|
|
164
|
+
)
|
|
165
|
+
data_dir_required = data_dir_required if data_dir_required else "n"
|
|
166
|
+
|
|
167
|
+
if data_dir_required not in ["y", "n"]:
|
|
168
|
+
print("invalid option selected")
|
|
169
|
+
sys.exit(1)
|
|
170
|
+
|
|
171
|
+
sol_dir_required = input(
|
|
172
|
+
"Do you require a solution file? y/n (leave empty for n): "
|
|
173
|
+
)
|
|
174
|
+
sol_dir_required = sol_dir_required if sol_dir_required else "n"
|
|
175
|
+
if sol_dir_required not in ["y", "n"]:
|
|
176
|
+
print("invalid option selected")
|
|
177
|
+
sys.exit(1)
|
|
178
|
+
|
|
179
|
+
non_notebook_grading = input(
|
|
180
|
+
"Will you grade a file different from a notebook? y/n (leave empty for n): ",
|
|
181
|
+
)
|
|
182
|
+
non_notebook_grading = non_notebook_grading if non_notebook_grading else "n"
|
|
183
|
+
if non_notebook_grading not in ["y", "n"]:
|
|
184
|
+
print("invalid option selected")
|
|
185
|
+
sys.exit(1)
|
|
186
|
+
|
|
187
|
+
extra_file_name = ""
|
|
188
|
+
if non_notebook_grading == "y":
|
|
189
|
+
extra_file_name = input(
|
|
190
|
+
"Name of the extra file to grade: ",
|
|
214
191
|
)
|
|
215
192
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
193
|
+
cpus = input("CPU Units (leave empty for 0.25): ")
|
|
194
|
+
cpus = cpus if cpus else "0.25"
|
|
195
|
+
|
|
196
|
+
if cpus not in ["0.25", "0.5", "0.75", "1"]:
|
|
197
|
+
print("invalid option selected")
|
|
198
|
+
sys.exit(1)
|
|
199
|
+
|
|
200
|
+
soft_memory = input("Memory Reservation (leave empty for 512m): ")
|
|
201
|
+
soft_memory = soft_memory if soft_memory else "512m"
|
|
202
|
+
|
|
203
|
+
if soft_memory not in [
|
|
204
|
+
"512m",
|
|
205
|
+
"768m",
|
|
206
|
+
"1024m",
|
|
207
|
+
"2048m",
|
|
208
|
+
"4096m",
|
|
209
|
+
"8192m",
|
|
210
|
+
"1g",
|
|
211
|
+
"2g",
|
|
212
|
+
"4g",
|
|
213
|
+
"8g",
|
|
214
|
+
]:
|
|
215
|
+
print("invalid option selected")
|
|
216
|
+
sys.exit(1)
|
|
217
|
+
|
|
218
|
+
hard_memory = input("Memory Limit (leave empty for 1g): ")
|
|
219
|
+
hard_memory = hard_memory if hard_memory else "1g"
|
|
220
|
+
|
|
221
|
+
if hard_memory not in [
|
|
222
|
+
"1024m",
|
|
223
|
+
"2048m",
|
|
224
|
+
"4096m",
|
|
225
|
+
"8192m",
|
|
226
|
+
"15000m",
|
|
227
|
+
"1g",
|
|
228
|
+
"2g",
|
|
229
|
+
"4g",
|
|
230
|
+
"8g",
|
|
231
|
+
"15g",
|
|
232
|
+
]:
|
|
233
|
+
print("invalid option selected")
|
|
234
|
+
sys.exit(1)
|
|
235
|
+
|
|
236
|
+
if grader_mvp == "y":
|
|
237
|
+
unit_test_filename = "unittests"
|
|
238
|
+
version = "1"
|
|
239
|
+
data_dir_required = "n"
|
|
240
|
+
sol_dir_required = "n"
|
|
241
|
+
non_notebook_grading = "n"
|
|
242
|
+
extra_file_name = ""
|
|
243
|
+
cpus = "0.25"
|
|
244
|
+
soft_memory = "512m"
|
|
245
|
+
hard_memory = "1g"
|
|
246
|
+
|
|
247
|
+
dockerfile = generate_dockerfile(
|
|
248
|
+
data_dir_required=data_dir_required,
|
|
249
|
+
sol_dir_required=sol_dir_required,
|
|
250
|
+
)
|
|
233
251
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
252
|
+
conf = f"""
|
|
253
|
+
ASSIGNMENT_NAME=C{course}M{module}_Assignment
|
|
254
|
+
UNIT_TESTS_NAME={unit_test_filename}
|
|
255
|
+
IMAGE_NAME={specialization}c{course}m{module}-grader
|
|
256
|
+
GRADER_VERSION={version}
|
|
257
|
+
TAG_ID=V$(GRADER_VERSION)
|
|
258
|
+
SUB_DIR=mount
|
|
259
|
+
MEMORY_LIMIT=4096
|
|
260
|
+
HARD_MEMORY={hard_memory}
|
|
261
|
+
CPUS={cpus}
|
|
262
|
+
SOFT_MEMORY={soft_memory}
|
|
263
|
+
"""
|
|
238
264
|
|
|
239
|
-
|
|
240
|
-
0.0,
|
|
241
|
-
f"Object required for grading not found. If you haven't completed the exercise this is expected. Otherwise, check your solution as grader omits cells that throw errors.\\n{additional_msg}",
|
|
242
|
-
err=True,
|
|
243
|
-
)
|
|
265
|
+
# assignment_name = f"C{course}M{module}_Assignment.ipynb"
|
|
244
266
|
|
|
245
|
-
|
|
267
|
+
# copy_assignment_to_submission_sh = generate_copy_assignment_script(
|
|
268
|
+
# extra_file_required=non_notebook_grading,
|
|
269
|
+
# assignment_name=assignment_name,
|
|
270
|
+
# extra_file_name=extra_file_name,
|
|
271
|
+
# )
|
|
246
272
|
|
|
247
|
-
|
|
273
|
+
makefile = copy_makefile()
|
|
248
274
|
|
|
275
|
+
grader_py = copy_grader_py()
|
|
249
276
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
277
|
+
entry_py = copy_entry_script(
|
|
278
|
+
sol_dir_required=sol_dir_required,
|
|
279
|
+
non_notebook_grading=non_notebook_grading,
|
|
280
|
+
extra_file_name=extra_file_name,
|
|
281
|
+
)
|
|
253
282
|
|
|
254
283
|
template_dict = {
|
|
255
|
-
"dockerfile": dedent(dockerfile
|
|
256
|
-
"makefile": dedent(makefile
|
|
284
|
+
"dockerfile": dedent(dockerfile),
|
|
285
|
+
"makefile": dedent(makefile),
|
|
257
286
|
"conf": dedent(conf[1:]),
|
|
258
|
-
"grader_py": dedent(grader_py
|
|
259
|
-
"entry_py": dedent(entry_py
|
|
287
|
+
"grader_py": dedent(grader_py),
|
|
288
|
+
"entry_py": dedent(entry_py),
|
|
289
|
+
# "copy_assignment_to_submission_sh": dedent(copy_assignment_to_submission_sh),
|
|
260
290
|
}
|
|
261
291
|
|
|
262
292
|
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.0b2
|
|
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=p-V3tVdD4pOdvAnNIMgMndm9u8oM-swvPyX7xrgkb0M,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=vtOic70NtJael8d5l9cX1KsNCwXKZrchhQgjHiSFhow,8898
|
|
9
|
+
dlai_grader/types.py,sha256=5uiFaF3aDn-vjxTp9ec-ND-PRqeeV2_NfPHS2ngGsRo,306
|
|
10
|
+
dlai_grader/templates/Makefile,sha256=PhRJ-87fU3IMqYMt9ChrAAfr2BPlk0uwogygLZItZL8,1795
|
|
11
|
+
dlai_grader/templates/grader.py,sha256=492Dzs3enoCGfDviq_mdnrzeF5e1qNl21i42M5tjv4Y,896
|
|
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=Y9cuwGuCrRHWfWmcvNP-Gh8mFcJL_JE0e9Ed09O7x6Q,2349
|
|
19
|
+
dlai_grader/templates/entry_py/solution_n_file_y.py,sha256=yHXK4iRVaxlhAwq3FiOfFEJdSRApfOgs3FMQtIe-A_c,2984
|
|
20
|
+
dlai_grader/templates/entry_py/solution_y_file_n.py,sha256=MKVmgXJVC1UtxtChsah7jUQ6-SL93kafZ02KrSayN0k,2397
|
|
21
|
+
dlai_grader/templates/entry_py/solution_y_file_y.py,sha256=gLauAYo-bieHR4ad20M-Zh1jYzoaYOyXHVKCXZReJ_A,3032
|
|
22
|
+
dlai_grader-2.0b2.dist-info/licenses/LICENSE,sha256=a_kch_UqdJPtyxk35QJr9O84K_koPixqWPYW9On4-io,1072
|
|
23
|
+
dlai_grader-2.0b2.dist-info/METADATA,sha256=V5bDW25vUyH7zf7mhe5hZKu-zTqxSxwIYYEBrYiaXU0,8776
|
|
24
|
+
dlai_grader-2.0b2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
25
|
+
dlai_grader-2.0b2.dist-info/entry_points.txt,sha256=4OcSAUIluONXa3ymViQ7CBQ2Lk52nb6xZnfph1rlMnk,71
|
|
26
|
+
dlai_grader-2.0b2.dist-info/top_level.txt,sha256=4YKtA3ztisFtx_g4hsGivy3J2NHnXxFziIMqawC8HWg,12
|
|
27
|
+
dlai_grader-2.0b2.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
|