dlai-grader 1.18.0__tar.gz → 1.20.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.
Files changed (22) hide show
  1. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/PKG-INFO +4 -2
  2. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/README.md +1 -1
  3. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader/__init__.py +1 -1
  4. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader/notebook.py +2 -2
  5. dlai_grader-1.20.0/dlai_grader/templates.py +264 -0
  6. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader.egg-info/PKG-INFO +4 -2
  7. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/setup.py +1 -1
  8. dlai-grader-1.18.0/dlai_grader/templates.py +0 -259
  9. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/LICENSE +0 -0
  10. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader/cli.py +0 -0
  11. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader/compiler.py +0 -0
  12. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader/config.py +0 -0
  13. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader/grading.py +0 -0
  14. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader/io.py +0 -0
  15. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader/py.typed +0 -0
  16. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader/types.py +0 -0
  17. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader.egg-info/SOURCES.txt +0 -0
  18. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader.egg-info/dependency_links.txt +0 -0
  19. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader.egg-info/entry_points.txt +0 -0
  20. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader.egg-info/requires.txt +0 -0
  21. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/dlai_grader.egg-info/top_level.txt +0 -0
  22. {dlai-grader-1.18.0 → dlai_grader-1.20.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dlai-grader
3
- Version: 1.18.0
3
+ Version: 1.20.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
@@ -11,6 +11,8 @@ Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: OS Independent
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
+ Requires-Dist: nbformat>=5.1.3
15
+ Requires-Dist: jupytext>=1.13.0
14
16
 
15
17
  # grader
16
18
  Automatic grading for DLAI courses. Designed to be compatible with Coursera's grading requirements.
@@ -40,7 +42,7 @@ dlai_grader --init
40
42
  This will ask you for:
41
43
  - Name of the course (abbreviation is recommended)
42
44
  - Number of the course
43
- - Number of the week
45
+ - Number of the week or module
44
46
  - Version of the grader (defaults to 1 but can be 2 or any other number)
45
47
 
46
48
  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:
@@ -6,6 +6,6 @@ from . import grading
6
6
  from . import types
7
7
 
8
8
 
9
- __version__ = "1.18.0"
9
+ __version__ = "1.20.0"
10
10
  __author__ = "Andres Zarta"
11
11
  __credits__ = "DeepLearning.AI"
@@ -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,264 @@
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
+ 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"]
49
+ """
50
+
51
+ if week:
52
+ W_OR_M = "W"
53
+ W_OR_M_num = week
54
+
55
+ if module:
56
+ W_OR_M = "M"
57
+ W_OR_M_num = module
58
+
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
+ """
68
+
69
+ makefile = """
70
+ .PHONY: learner build entry submit-solution upgrade test grade mem zip clean upload move-zip move-learner tag undeletable uneditable versioning upgrade sync
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
93
+
94
+ versioning:
95
+ dlai_grader --versioning
96
+
97
+ tag:
98
+ dlai_grader --tag
99
+
100
+ undeletable:
101
+ dlai_grader --undeletable
102
+
103
+ uneditable:
104
+ dlai_grader --uneditable
105
+
106
+ upgrade:
107
+ dlai_grader --upgrade
108
+
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
+
112
+ grade:
113
+ dlai_grader --grade --partids=$(PARTIDS) --docker=$(IMAGE_NAME):$(TAG_ID) --memory=$(MEMORY_LIMIT) --submission=$(SUB_DIR)
114
+
115
+ mem:
116
+ memthis $(PARTIDS)
117
+
118
+ zip:
119
+ zip -r $(IMAGE_NAME)$(TAG_ID).zip .
120
+
121
+ clean:
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)
125
+
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
+
129
+ """
130
+
131
+ grader_py = """
132
+ from types import ModuleType, FunctionType
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
136
+
137
+
138
+ def part_1(
139
+ learner_mod: learner_submission, solution_mod: Optional[ModuleType]
140
+ ) -> grading_function:
141
+ @object_to_grade(learner_mod, "learner_func")
142
+ def g(learner_func: FunctionType) -> List[test_case]:
143
+
144
+ t = test_case()
145
+ if not isinstance(learner_func, FunctionType):
146
+ t.failed = True
147
+ t.msg = "learner_func has incorrect type"
148
+ t.want = FunctionType
149
+ t.got = type(learner_func)
150
+ return [t]
151
+
152
+ cases: List[test_case] = []
153
+
154
+ return cases
155
+
156
+ return g
157
+
158
+
159
+ def handle_part_id(part_id: str) -> grading_wrapper:
160
+ grader_dict: Dict[str, grading_wrapper] = {
161
+ "": part_1,
162
+ }
163
+ return grader_dict[part_id]
164
+ """
165
+
166
+ entry_py = """
167
+ from dlai_grader.config import Config
168
+ from dlai_grader.compiler import compile_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
181
+
182
+
183
+ def main() -> None:
184
+ c = Config()
185
+
186
+ copy_submission_to_workdir()
187
+
188
+ try:
189
+ nb = read_notebook(c.submission_file_path)
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
+ )
196
+
197
+ if not notebook_is_up_to_date(nb):
198
+ 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)}."
199
+
200
+ send_feedback(0.0, msg)
201
+
202
+ transformations = [cut_notebook(), keep_tagged_cells()]
203
+
204
+ for t in transformations:
205
+ nb = t(nb)
206
+
207
+ script = notebook_to_script(nb)
208
+
209
+ try:
210
+ learner_mod = compile_module(script, "learner_mod", verbose=False)
211
+ except Exception as e:
212
+ send_feedback(
213
+ 0.0,
214
+ f"There was a problem compiling the code from your notebook, please check that you saved before submitting. Details:\\n{str(e)}",
215
+ )
216
+
217
+ solution_nb = read_notebook(c.solution_file_path)
218
+
219
+ for t in transformations:
220
+ solution_nb = t(solution_nb)
221
+
222
+ solution_script = notebook_to_script(solution_nb)
223
+ solution_mod = compile_module(solution_script, "solution_mod", verbose=False)
224
+
225
+ g_func = handle_part_id(c.part_id)(learner_mod, solution_mod)
226
+
227
+ try:
228
+ cases = g_func()
229
+ except Exception as e:
230
+ send_feedback(
231
+ 0.0,
232
+ f"There was an error grading your submission. Details:\\n{str(e)}",
233
+ err=True,
234
+ )
235
+
236
+ if graded_obj_missing(cases):
237
+ additional_msg = ""
238
+ if partial_grading_enabled(nb):
239
+ additional_msg = "The # grade-up-to-here comment in the notebook might be causing the problem."
240
+
241
+ send_feedback(
242
+ 0.0,
243
+ f"Unable to find object required for grading in your code.\\n{additional_msg}",
244
+ err=True,
245
+ )
246
+
247
+ score, feedback = compute_grading_score(cases)
248
+
249
+ send_feedback(score, feedback)
250
+
251
+
252
+ if __name__ == "__main__":
253
+ main()
254
+ """
255
+
256
+ template_dict = {
257
+ "dockerfile": dedent(dockerfile[1:]),
258
+ "makefile": dedent(makefile[1:]),
259
+ "conf": dedent(conf[1:]),
260
+ "grader_py": dedent(grader_py[1:]),
261
+ "entry_py": dedent(entry_py[1:]),
262
+ }
263
+
264
+ return template_dict
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dlai-grader
3
- Version: 1.18.0
3
+ Version: 1.20.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
@@ -11,6 +11,8 @@ Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: OS Independent
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
+ Requires-Dist: nbformat>=5.1.3
15
+ Requires-Dist: jupytext>=1.13.0
14
16
 
15
17
  # grader
16
18
  Automatic grading for DLAI courses. Designed to be compatible with Coursera's grading requirements.
@@ -40,7 +42,7 @@ dlai_grader --init
40
42
  This will ask you for:
41
43
  - Name of the course (abbreviation is recommended)
42
44
  - Number of the course
43
- - Number of the week
45
+ - Number of the week or module
44
46
  - Version of the grader (defaults to 1 but can be 2 or any other number)
45
47
 
46
48
  This will generate a file system tree like this:
@@ -5,7 +5,7 @@ with open("README.md", "r") as f:
5
5
 
6
6
  setup(
7
7
  name="dlai-grader",
8
- version="1.18.0",
8
+ version="1.20.0",
9
9
  description="Grading utilities for DLAI courses",
10
10
  url="https://github.com/https-deeplearning-ai/grader",
11
11
  author="Andres Zarta",
@@ -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