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.

Files changed (22) hide show
  1. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/PKG-INFO +2 -2
  2. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/README.md +1 -1
  3. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/__init__.py +1 -1
  4. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/notebook.py +2 -2
  5. dlai-grader-1.19.0/dlai_grader/templates.py +261 -0
  6. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/PKG-INFO +2 -2
  7. {dlai-grader-1.18.0 → dlai-grader-1.19.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.19.0}/LICENSE +0 -0
  10. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/cli.py +0 -0
  11. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/compiler.py +0 -0
  12. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/config.py +0 -0
  13. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/grading.py +0 -0
  14. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/io.py +0 -0
  15. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/py.typed +0 -0
  16. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader/types.py +0 -0
  17. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/SOURCES.txt +0 -0
  18. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/dependency_links.txt +0 -0
  19. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/entry_points.txt +0 -0
  20. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/requires.txt +0 -0
  21. {dlai-grader-1.18.0 → dlai-grader-1.19.0}/dlai_grader.egg-info/top_level.txt +0 -0
  22. {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.18.0
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:
@@ -6,6 +6,6 @@ from . import grading
6
6
  from . import types
7
7
 
8
8
 
9
- __version__ = "1.18.0"
9
+ __version__ = "1.19.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,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.18.0
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:
@@ -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.19.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