dlai-grader 1.18.0__tar.gz → 1.19.0__tar.gz
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-1.18.0 → dlai-grader-1.19.0}/PKG-INFO +2 -2
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/README.md +1 -1
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/__init__.py +1 -1
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/notebook.py +2 -2
- dlai-grader-1.19.0/dlai_grader/templates.py +261 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/PKG-INFO +2 -2
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/setup.py +1 -1
- dlai-grader-1.18.0/dlai_grader/templates.py +0 -259
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/LICENSE +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/cli.py +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/compiler.py +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/config.py +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/grading.py +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/io.py +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/py.typed +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/types.py +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/SOURCES.txt +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/dependency_links.txt +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/entry_points.txt +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/requires.txt +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/top_level.txt +0 -0
- {dlai-grader-1.18.0 → dlai-grader-1.19.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dlai-grader
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.19.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
|
|
@@ -40,7 +40,7 @@ dlai_grader --init
|
|
|
40
40
|
This will ask you for:
|
|
41
41
|
- Name of the course (abbreviation is recommended)
|
|
42
42
|
- Number of the course
|
|
43
|
-
- Number of the week
|
|
43
|
+
- Number of the week or module
|
|
44
44
|
- Version of the grader (defaults to 1 but can be 2 or any other number)
|
|
45
45
|
|
|
46
46
|
This will generate a file system tree like this:
|
|
@@ -26,7 +26,7 @@ dlai_grader --init
|
|
|
26
26
|
This will ask you for:
|
|
27
27
|
- Name of the course (abbreviation is recommended)
|
|
28
28
|
- Number of the course
|
|
29
|
-
- Number of the week
|
|
29
|
+
- Number of the week or module
|
|
30
30
|
- Version of the grader (defaults to 1 but can be 2 or any other number)
|
|
31
31
|
|
|
32
32
|
This will generate a file system tree like this:
|
|
@@ -19,7 +19,7 @@ def notebook_to_script(
|
|
|
19
19
|
|
|
20
20
|
def cut_notebook(
|
|
21
21
|
regex_pattern: str = "(grade)(.|[ \t]*)(up)(.|[ \t]*)(to)(.|[ \t]*)(here)",
|
|
22
|
-
) -> NotebookNode:
|
|
22
|
+
) -> Callable[[NotebookNode], NotebookNode]:
|
|
23
23
|
"""Cuts a notebook, this allows for partial grading. Written as a closure so it can be consumed as a functional option for notebooks.
|
|
24
24
|
Args:
|
|
25
25
|
regex_pattern (str): Regexp pattern to look for. Cells after match will be omitted.
|
|
@@ -29,7 +29,7 @@ def cut_notebook(
|
|
|
29
29
|
|
|
30
30
|
def inner(
|
|
31
31
|
notebook: NotebookNode,
|
|
32
|
-
):
|
|
32
|
+
) -> NotebookNode:
|
|
33
33
|
"""Cuts a notebook by excluding all cells after a pattern is matched.
|
|
34
34
|
Args:
|
|
35
35
|
notebook (NotebookNode): Notebook to filter.
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
from textwrap import dedent
|
|
2
|
+
from typing import Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def load_templates() -> Dict[str, str]:
|
|
6
|
+
specialization = input("Name of the specialization: ")
|
|
7
|
+
course = input("Number of the course: ")
|
|
8
|
+
week_or_module = input("Weeks or Modules?\n1 for weeks\n2 for modules: ")
|
|
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
|
+
version = input("Version of the grader (leave empty for version 1): ")
|
|
21
|
+
version = "1" if not version else version
|
|
22
|
+
|
|
23
|
+
dockerfile = """
|
|
24
|
+
FROM continuumio/miniconda3@sha256:d601a04ea48fd45e60808c7072243d33703d29434d2067816b7f26b0705d889a
|
|
25
|
+
|
|
26
|
+
RUN apk update && apk add libstdc++
|
|
27
|
+
|
|
28
|
+
COPY requirements.txt .
|
|
29
|
+
|
|
30
|
+
RUN pip install -r requirements.txt && \
|
|
31
|
+
rm requirements.txt
|
|
32
|
+
|
|
33
|
+
RUN mkdir /grader && \
|
|
34
|
+
mkdir /grader/submission
|
|
35
|
+
|
|
36
|
+
COPY .conf /grader/.conf
|
|
37
|
+
COPY data/ /grader/data/
|
|
38
|
+
COPY solution/ /grader/solution/
|
|
39
|
+
COPY entry.py /grader/entry.py
|
|
40
|
+
COPY grader.py /grader/grader.py
|
|
41
|
+
|
|
42
|
+
RUN chmod a+rwx /grader/
|
|
43
|
+
|
|
44
|
+
WORKDIR /grader/
|
|
45
|
+
|
|
46
|
+
ENTRYPOINT ["python", "entry.py"]
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
if week:
|
|
50
|
+
W_OR_M = "W"
|
|
51
|
+
W_OR_M_num = week
|
|
52
|
+
|
|
53
|
+
if module:
|
|
54
|
+
W_OR_M = "M"
|
|
55
|
+
W_OR_M_num = module
|
|
56
|
+
|
|
57
|
+
conf = f"""
|
|
58
|
+
ASSIGNMENT_NAME=C{course}{W_OR_M}{W_OR_M_num}_Assignment
|
|
59
|
+
IMAGE_NAME={specialization}c{course}{W_OR_M.lower()}{W_OR_M_num}-grader
|
|
60
|
+
GRADER_VERSION={version}
|
|
61
|
+
TAG_ID=V$(GRADER_VERSION)
|
|
62
|
+
SUB_DIR=mount
|
|
63
|
+
MEMORY_LIMIT=4096
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
makefile = """
|
|
67
|
+
.PHONY: learner build entry submit-solution upgrade test grade mem zip clean upload move-zip move-learner tag undeletable uneditable versioning upgrade sync
|
|
68
|
+
|
|
69
|
+
include .conf
|
|
70
|
+
|
|
71
|
+
PARTIDS = ""
|
|
72
|
+
OS := $(shell uname)
|
|
73
|
+
|
|
74
|
+
sync:
|
|
75
|
+
cp mount/submission.ipynb ../$(ASSIGNMENT_NAME)_Solution.ipynb
|
|
76
|
+
cp learner/$(ASSIGNMENT_NAME).ipynb ../$(ASSIGNMENT_NAME).ipynb
|
|
77
|
+
cp mount/unittests.py ../unittests.py
|
|
78
|
+
|
|
79
|
+
learner:
|
|
80
|
+
dlai_grader --learner --output_notebook=./learner/$(ASSIGNMENT_NAME).ipynb
|
|
81
|
+
|
|
82
|
+
build:
|
|
83
|
+
docker build -t $(IMAGE_NAME):$(TAG_ID) .
|
|
84
|
+
|
|
85
|
+
debug:
|
|
86
|
+
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)
|
|
87
|
+
|
|
88
|
+
submit-solution:
|
|
89
|
+
cp solution/solution.ipynb mount/submission.ipynb
|
|
90
|
+
|
|
91
|
+
versioning:
|
|
92
|
+
dlai_grader --versioning
|
|
93
|
+
|
|
94
|
+
tag:
|
|
95
|
+
dlai_grader --tag
|
|
96
|
+
|
|
97
|
+
undeletable:
|
|
98
|
+
dlai_grader --undeletable
|
|
99
|
+
|
|
100
|
+
uneditable:
|
|
101
|
+
dlai_grader --uneditable
|
|
102
|
+
|
|
103
|
+
upgrade:
|
|
104
|
+
dlai_grader --upgrade
|
|
105
|
+
|
|
106
|
+
test:
|
|
107
|
+
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)
|
|
108
|
+
|
|
109
|
+
grade:
|
|
110
|
+
dlai_grader --grade --partids=$(PARTIDS) --docker=$(IMAGE_NAME):$(TAG_ID) --memory=$(MEMORY_LIMIT) --submission=$(SUB_DIR)
|
|
111
|
+
|
|
112
|
+
mem:
|
|
113
|
+
memthis $(PARTIDS)
|
|
114
|
+
|
|
115
|
+
zip:
|
|
116
|
+
zip -r $(IMAGE_NAME)$(TAG_ID).zip .
|
|
117
|
+
|
|
118
|
+
clean:
|
|
119
|
+
find . -maxdepth 1 -type f -name "*.zip" -exec rm {} +
|
|
120
|
+
docker rm $$(docker ps -qa --no-trunc --filter "status=exited")
|
|
121
|
+
docker rmi $$(docker images --filter "dangling=true" -q --no-trunc)
|
|
122
|
+
|
|
123
|
+
upload:
|
|
124
|
+
coursera_autograder --timeout 1800 upload --grader-memory-limit $(MEMORY_LIMIT) --grading-timeout 1800 $(IMAGE_NAME)$(TAG_ID).zip $(COURSE_ID) $(ITEM_ID) $(PART_ID)
|
|
125
|
+
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
grader_py = """
|
|
129
|
+
from types import ModuleType, FunctionType
|
|
130
|
+
from typing import Dict, List, Optional
|
|
131
|
+
from dlai_grader.grading import test_case, object_to_grade
|
|
132
|
+
from dlai_grader.types import grading_function, grading_wrapper, learner_submission
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def part_1(
|
|
136
|
+
learner_mod: learner_submission, solution_mod: Optional[ModuleType]
|
|
137
|
+
) -> grading_function:
|
|
138
|
+
@object_to_grade(learner_mod, "learner_func")
|
|
139
|
+
def g(learner_func: FunctionType) -> List[test_case]:
|
|
140
|
+
|
|
141
|
+
t = test_case()
|
|
142
|
+
if not isinstance(learner_func, FunctionType):
|
|
143
|
+
t.failed = True
|
|
144
|
+
t.msg = "learner_func has incorrect type"
|
|
145
|
+
t.want = FunctionType
|
|
146
|
+
t.got = type(learner_func)
|
|
147
|
+
return [t]
|
|
148
|
+
|
|
149
|
+
cases: List[test_case] = []
|
|
150
|
+
|
|
151
|
+
return cases
|
|
152
|
+
|
|
153
|
+
return g
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def handle_part_id(part_id: str) -> grading_wrapper:
|
|
157
|
+
grader_dict: Dict[str, grading_wrapper] = {
|
|
158
|
+
"": part_1,
|
|
159
|
+
}
|
|
160
|
+
return grader_dict[part_id]
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
entry_py = """
|
|
164
|
+
from dlai_grader.config import Config
|
|
165
|
+
from dlai_grader.compiler import compile_module
|
|
166
|
+
from dlai_grader.io import read_notebook, copy_submission_to_workdir, send_feedback
|
|
167
|
+
|
|
168
|
+
from dlai_grader.notebook import (
|
|
169
|
+
notebook_to_script,
|
|
170
|
+
keep_tagged_cells,
|
|
171
|
+
notebook_is_up_to_date,
|
|
172
|
+
notebook_version,
|
|
173
|
+
cut_notebook,
|
|
174
|
+
partial_grading_enabled,
|
|
175
|
+
)
|
|
176
|
+
from dlai_grader.grading import compute_grading_score, graded_obj_missing
|
|
177
|
+
from grader import handle_part_id
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def main() -> None:
|
|
181
|
+
c = Config()
|
|
182
|
+
|
|
183
|
+
copy_submission_to_workdir()
|
|
184
|
+
|
|
185
|
+
try:
|
|
186
|
+
nb = read_notebook(c.submission_file_path)
|
|
187
|
+
except Exception as e:
|
|
188
|
+
send_feedback(
|
|
189
|
+
0.0,
|
|
190
|
+
f"There was a problem reading your notebook. Details:\\n{str(e)}",
|
|
191
|
+
err=True,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
if not notebook_is_up_to_date(nb):
|
|
195
|
+
msg = f"You are submitting a version of the assignment that is behind the latest version.\\nThe latest version is {c.latest_version} and you are on version {notebook_version(nb)}."
|
|
196
|
+
|
|
197
|
+
send_feedback(0.0, msg)
|
|
198
|
+
|
|
199
|
+
transformations = [cut_notebook(), keep_tagged_cells()]
|
|
200
|
+
|
|
201
|
+
for t in transformations:
|
|
202
|
+
nb = t(nb)
|
|
203
|
+
|
|
204
|
+
script = notebook_to_script(nb)
|
|
205
|
+
|
|
206
|
+
try:
|
|
207
|
+
learner_mod = compile_module(script, "learner_mod", verbose=False)
|
|
208
|
+
except Exception as e:
|
|
209
|
+
send_feedback(
|
|
210
|
+
0.0,
|
|
211
|
+
f"There was a problem compiling the code from your notebook, please check that you saved before submitting. Details:\\n{str(e)}",
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
solution_nb = read_notebook(c.solution_file_path)
|
|
215
|
+
|
|
216
|
+
for t in transformations:
|
|
217
|
+
solution_nb = t(solution_nb)
|
|
218
|
+
|
|
219
|
+
solution_script = notebook_to_script(solution_nb)
|
|
220
|
+
solution_mod = compile_module(solution_script, "solution_mod", verbose=False)
|
|
221
|
+
|
|
222
|
+
g_func = handle_part_id(c.part_id)(learner_mod, solution_mod)
|
|
223
|
+
|
|
224
|
+
try:
|
|
225
|
+
cases = g_func()
|
|
226
|
+
except Exception as e:
|
|
227
|
+
send_feedback(
|
|
228
|
+
0.0,
|
|
229
|
+
f"There was an error grading your submission. Details:\\n{str(e)}",
|
|
230
|
+
err=True,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
if graded_obj_missing(cases):
|
|
234
|
+
additional_msg = ""
|
|
235
|
+
if partial_grading_enabled(nb):
|
|
236
|
+
additional_msg = "The # grade-up-to-here comment in the notebook might be causing the problem."
|
|
237
|
+
|
|
238
|
+
send_feedback(
|
|
239
|
+
0.0,
|
|
240
|
+
f"Unable to find object required for grading in your code.\\n{additional_msg}",
|
|
241
|
+
err=True,
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
score, feedback = compute_grading_score(cases)
|
|
245
|
+
|
|
246
|
+
send_feedback(score, feedback)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
if __name__ == "__main__":
|
|
250
|
+
main()
|
|
251
|
+
"""
|
|
252
|
+
|
|
253
|
+
template_dict = {
|
|
254
|
+
"dockerfile": dedent(dockerfile[1:]),
|
|
255
|
+
"makefile": dedent(makefile[1:]),
|
|
256
|
+
"conf": dedent(conf[1:]),
|
|
257
|
+
"grader_py": dedent(grader_py[1:]),
|
|
258
|
+
"entry_py": dedent(entry_py[1:]),
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return template_dict
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dlai-grader
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.19.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
|
|
@@ -40,7 +40,7 @@ dlai_grader --init
|
|
|
40
40
|
This will ask you for:
|
|
41
41
|
- Name of the course (abbreviation is recommended)
|
|
42
42
|
- Number of the course
|
|
43
|
-
- Number of the week
|
|
43
|
+
- Number of the week or module
|
|
44
44
|
- Version of the grader (defaults to 1 but can be 2 or any other number)
|
|
45
45
|
|
|
46
46
|
This will generate a file system tree like this:
|
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
from textwrap import dedent
|
|
2
|
-
from typing import Dict
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def load_templates() -> Dict[str, str]:
|
|
6
|
-
specialization = input("Name of the specialization: ")
|
|
7
|
-
course = input("Number of the course: ")
|
|
8
|
-
week = input("Number of the week: ")
|
|
9
|
-
version = input("Version of the grader (leave empty for version 1): ")
|
|
10
|
-
version = "1" if not version else version
|
|
11
|
-
|
|
12
|
-
dockerfile = """
|
|
13
|
-
FROM continuumio/miniconda3@sha256:d601a04ea48fd45e60808c7072243d33703d29434d2067816b7f26b0705d889a
|
|
14
|
-
|
|
15
|
-
RUN apk update && apk add libstdc++
|
|
16
|
-
|
|
17
|
-
COPY requirements.txt .
|
|
18
|
-
|
|
19
|
-
RUN pip install -r requirements.txt && \
|
|
20
|
-
rm requirements.txt
|
|
21
|
-
|
|
22
|
-
RUN mkdir /grader && \
|
|
23
|
-
mkdir /grader/submission
|
|
24
|
-
|
|
25
|
-
COPY .conf /grader/.conf
|
|
26
|
-
COPY data/ /grader/data/
|
|
27
|
-
COPY solution/ /grader/solution/
|
|
28
|
-
COPY entry.py /grader/entry.py
|
|
29
|
-
COPY grader.py /grader/grader.py
|
|
30
|
-
|
|
31
|
-
RUN chmod a+rwx /grader/
|
|
32
|
-
|
|
33
|
-
WORKDIR /grader/
|
|
34
|
-
|
|
35
|
-
ENTRYPOINT ["python", "entry.py"]
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
conf = f"""
|
|
39
|
-
ASSIGNMENT_NAME=C{course}W{week}_Assignment
|
|
40
|
-
IMAGE_NAME={specialization}c{course}w{week}-grader
|
|
41
|
-
GRADER_VERSION={version}
|
|
42
|
-
TAG_ID=V$(GRADER_VERSION)
|
|
43
|
-
SUB_DIR=mount
|
|
44
|
-
MEMORY_LIMIT=4096
|
|
45
|
-
LINUX_UPLOAD_DIR='/mnt/c/Users/Andres/dlai/upload'
|
|
46
|
-
MAC_UPLOAD_DIR='/Users/andreszarta/Desktop/upload-temp'
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
makefile = """
|
|
50
|
-
.PHONY: learner build entry submit-solution upgrade test grade mem zip clean upload move-zip move-learner tag undeletable uneditable versioning upgrade sync
|
|
51
|
-
|
|
52
|
-
include .conf
|
|
53
|
-
|
|
54
|
-
PARTIDS = ""
|
|
55
|
-
OS := $(shell uname)
|
|
56
|
-
|
|
57
|
-
sync:
|
|
58
|
-
cp mount/submission.ipynb ../$(ASSIGNMENT_NAME)_Solution.ipynb
|
|
59
|
-
cp learner/$(ASSIGNMENT_NAME).ipynb ../$(ASSIGNMENT_NAME).ipynb
|
|
60
|
-
cp mount/unittests.py ../unittests.py
|
|
61
|
-
|
|
62
|
-
learner:
|
|
63
|
-
dlai_grader --learner --output_notebook=./learner/$(ASSIGNMENT_NAME).ipynb
|
|
64
|
-
|
|
65
|
-
build:
|
|
66
|
-
docker build -t $(IMAGE_NAME):$(TAG_ID) .
|
|
67
|
-
|
|
68
|
-
debug:
|
|
69
|
-
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)
|
|
70
|
-
|
|
71
|
-
submit-solution:
|
|
72
|
-
cp solution/solution.ipynb mount/submission.ipynb
|
|
73
|
-
|
|
74
|
-
versioning:
|
|
75
|
-
dlai_grader --versioning
|
|
76
|
-
|
|
77
|
-
tag:
|
|
78
|
-
dlai_grader --tag
|
|
79
|
-
|
|
80
|
-
undeletable:
|
|
81
|
-
dlai_grader --undeletable
|
|
82
|
-
|
|
83
|
-
uneditable:
|
|
84
|
-
dlai_grader --uneditable
|
|
85
|
-
|
|
86
|
-
upgrade:
|
|
87
|
-
dlai_grader --upgrade
|
|
88
|
-
|
|
89
|
-
test:
|
|
90
|
-
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)
|
|
91
|
-
|
|
92
|
-
grade:
|
|
93
|
-
dlai_grader --grade --partids=$(PARTIDS) --docker=$(IMAGE_NAME):$(TAG_ID) --memory=$(MEMORY_LIMIT) --submission=$(SUB_DIR)
|
|
94
|
-
|
|
95
|
-
mem:
|
|
96
|
-
memthis $(PARTIDS)
|
|
97
|
-
|
|
98
|
-
zip:
|
|
99
|
-
zip -r $(IMAGE_NAME)$(TAG_ID).zip .
|
|
100
|
-
|
|
101
|
-
clean:
|
|
102
|
-
find . -maxdepth 1 -type f -name "*.zip" -exec rm {} +
|
|
103
|
-
docker rm $$(docker ps -qa --no-trunc --filter "status=exited")
|
|
104
|
-
docker rmi $$(docker images --filter "dangling=true" -q --no-trunc)
|
|
105
|
-
|
|
106
|
-
upload:
|
|
107
|
-
coursera_autograder --timeout 1800 upload --grader-memory-limit $(MEMORY_LIMIT) --grading-timeout 1800 $(IMAGE_NAME)$(TAG_ID).zip $(COURSE_ID) $(ITEM_ID) $(PART_ID)
|
|
108
|
-
|
|
109
|
-
move-zip:
|
|
110
|
-
if [[ "$(OS)" == "Darwin" ]]; \
|
|
111
|
-
then \
|
|
112
|
-
mv $(IMAGE_NAME)$(TAG_ID).zip $(MAC_UPLOAD_DIR); \
|
|
113
|
-
else \
|
|
114
|
-
mv $(IMAGE_NAME)$(TAG_ID).zip $(LINUX_UPLOAD_DIR); \
|
|
115
|
-
fi
|
|
116
|
-
|
|
117
|
-
move-learner:
|
|
118
|
-
if [[ "$(OS)" == "Darwin" ]]; \
|
|
119
|
-
then \
|
|
120
|
-
cp learner/$(ASSIGNMENT_NAME).ipynb $(MAC_UPLOAD_DIR); \
|
|
121
|
-
else \
|
|
122
|
-
cp learner/$(ASSIGNMENT_NAME).ipynb $(LINUX_UPLOAD_DIR); \
|
|
123
|
-
fi
|
|
124
|
-
"""
|
|
125
|
-
|
|
126
|
-
grader_py = """
|
|
127
|
-
from types import ModuleType, FunctionType
|
|
128
|
-
from typing import Dict, List, Optional
|
|
129
|
-
from dlai_grader.grading import test_case, object_to_grade
|
|
130
|
-
from dlai_grader.types import grading_function, grading_wrapper, learner_submission
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
def part_1(
|
|
134
|
-
learner_mod: learner_submission, solution_mod: Optional[ModuleType]
|
|
135
|
-
) -> grading_function:
|
|
136
|
-
@object_to_grade(learner_mod, "learner_func")
|
|
137
|
-
def g(learner_func: FunctionType) -> List[test_case]:
|
|
138
|
-
|
|
139
|
-
t = test_case()
|
|
140
|
-
if not isinstance(learner_func, FunctionType):
|
|
141
|
-
t.failed = True
|
|
142
|
-
t.msg = "learner_func has incorrect type"
|
|
143
|
-
t.want = FunctionType
|
|
144
|
-
t.got = type(learner_func)
|
|
145
|
-
return [t]
|
|
146
|
-
|
|
147
|
-
cases: List[test_case] = []
|
|
148
|
-
|
|
149
|
-
return cases
|
|
150
|
-
|
|
151
|
-
return g
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
def handle_part_id(part_id: str) -> grading_wrapper:
|
|
155
|
-
grader_dict: Dict[str, grading_wrapper] = {
|
|
156
|
-
"": part_1,
|
|
157
|
-
}
|
|
158
|
-
return grader_dict[part_id]
|
|
159
|
-
"""
|
|
160
|
-
|
|
161
|
-
entry_py = """
|
|
162
|
-
from dlai_grader.config import Config
|
|
163
|
-
from dlai_grader.compiler import compile_module
|
|
164
|
-
from dlai_grader.io import read_notebook, copy_submission_to_workdir, send_feedback
|
|
165
|
-
|
|
166
|
-
from dlai_grader.notebook import (
|
|
167
|
-
notebook_to_script,
|
|
168
|
-
keep_tagged_cells,
|
|
169
|
-
notebook_is_up_to_date,
|
|
170
|
-
notebook_version,
|
|
171
|
-
cut_notebook,
|
|
172
|
-
partial_grading_enabled,
|
|
173
|
-
)
|
|
174
|
-
from dlai_grader.grading import compute_grading_score, graded_obj_missing
|
|
175
|
-
from grader import handle_part_id
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
def main() -> None:
|
|
179
|
-
c = Config()
|
|
180
|
-
|
|
181
|
-
copy_submission_to_workdir()
|
|
182
|
-
|
|
183
|
-
try:
|
|
184
|
-
nb = read_notebook(c.submission_file_path)
|
|
185
|
-
except Exception as e:
|
|
186
|
-
send_feedback(
|
|
187
|
-
0.0,
|
|
188
|
-
f"There was a problem reading your notebook. Details:\\n{str(e)}",
|
|
189
|
-
err=True,
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
if not notebook_is_up_to_date(nb):
|
|
193
|
-
msg = f"You are submitting a version of the assignment that is behind the latest version.\\nThe latest version is {c.latest_version} and you are on version {notebook_version(nb)}."
|
|
194
|
-
|
|
195
|
-
send_feedback(0.0, msg)
|
|
196
|
-
|
|
197
|
-
transformations = [cut_notebook(), keep_tagged_cells()]
|
|
198
|
-
|
|
199
|
-
for t in transformations:
|
|
200
|
-
nb = t(nb)
|
|
201
|
-
|
|
202
|
-
script = notebook_to_script(nb)
|
|
203
|
-
|
|
204
|
-
try:
|
|
205
|
-
learner_mod = compile_module(script, "learner_mod", verbose=False)
|
|
206
|
-
except Exception as e:
|
|
207
|
-
send_feedback(
|
|
208
|
-
0.0,
|
|
209
|
-
f"There was a problem compiling the code from your notebook, please check that you saved before submitting. Details:\\n{str(e)}",
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
solution_nb = read_notebook(c.solution_file_path)
|
|
213
|
-
|
|
214
|
-
for t in transformations:
|
|
215
|
-
solution_nb = t(solution_nb)
|
|
216
|
-
|
|
217
|
-
solution_script = notebook_to_script(solution_nb)
|
|
218
|
-
solution_mod = compile_module(solution_script, "solution_mod", verbose=False)
|
|
219
|
-
|
|
220
|
-
g_func = handle_part_id(c.part_id)(learner_mod, solution_mod)
|
|
221
|
-
|
|
222
|
-
try:
|
|
223
|
-
cases = g_func()
|
|
224
|
-
except Exception as e:
|
|
225
|
-
send_feedback(
|
|
226
|
-
0.0,
|
|
227
|
-
f"There was an error grading your submission. Details:\\n{str(e)}",
|
|
228
|
-
err=True,
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
if graded_obj_missing(cases):
|
|
232
|
-
additional_msg = ""
|
|
233
|
-
if partial_grading_enabled(nb):
|
|
234
|
-
additional_msg = "The # grade-up-to-here comment in the notebook might be causing the problem."
|
|
235
|
-
|
|
236
|
-
send_feedback(
|
|
237
|
-
0.0,
|
|
238
|
-
f"Unable to find object required for grading in your code.\\n{additional_msg}",
|
|
239
|
-
err=True,
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
score, feedback = compute_grading_score(cases)
|
|
243
|
-
|
|
244
|
-
send_feedback(score, feedback)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if __name__ == "__main__":
|
|
248
|
-
main()
|
|
249
|
-
"""
|
|
250
|
-
|
|
251
|
-
template_dict = {
|
|
252
|
-
"dockerfile": dedent(dockerfile[1:]),
|
|
253
|
-
"makefile": dedent(makefile[1:]),
|
|
254
|
-
"conf": dedent(conf[1:]),
|
|
255
|
-
"grader_py": dedent(grader_py[1:]),
|
|
256
|
-
"entry_py": dedent(entry_py[1:]),
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
return template_dict
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|