Coverage for e2xgrader/server_extensions/apps/e2xgraderapi/apihandlers.py: 56%
93 statements
« prev ^ index » next coverage.py v7.4.2, created at 2024-03-14 13:22 +0100
« prev ^ index » next coverage.py v7.4.2, created at 2024-03-14 13:22 +0100
1import json
3from e2xcore.handlers.base import E2xApiHandler
4from nbgrader.server_extensions.formgrader.apihandlers import (
5 AssignmentCollectionHandler,
6 AssignmentHandler,
7)
8from nbgrader.server_extensions.formgrader.base import check_notebook_dir, check_xsrf
9from tornado import web
11from e2xgrader.exporters import GradeExporter
14class E2xAssignmentCollectionHandler(E2xApiHandler, AssignmentCollectionHandler):
15 """
16 Inherit from E2xApiHandler to overwrite the internal NbgraderAPI with the E2xAPI
17 """
19 @web.authenticated
20 @check_xsrf
21 @check_notebook_dir
22 def get(self):
23 include_score = self.get_argument("include_score", "True").lower() == "true"
24 self.write(json.dumps(self.api.get_assignments(include_score=include_score)))
27class E2xAssignmentHandler(E2xApiHandler, AssignmentHandler):
28 """
29 Inherit from E2xApiHandler to overwrite the internal NbgraderAPI with the E2xAPI
30 """
32 @web.authenticated
33 @check_xsrf
34 @check_notebook_dir
35 def get(self, assignment_id):
36 include_score = self.get_argument("include_score", "True").lower() == "true"
37 assignment = self.api.get_assignment(assignment_id, include_score=include_score)
38 if assignment is None:
39 raise web.HTTPError(404)
40 self.write(json.dumps(assignment))
43class SolutionCellCollectionHandler(E2xApiHandler):
44 @web.authenticated
45 @check_xsrf
46 def get(self, assignment_id, notebook_id):
47 cells = self.api.get_solution_cell_ids(assignment_id, notebook_id)
48 self.write(json.dumps(cells))
51class SubmittedTaskCollectionHandler(E2xApiHandler):
52 @web.authenticated
53 @check_xsrf
54 def get(self, assignment_id, notebook_id, task_id):
55 submissions = self.api.get_task_submissions(assignment_id, notebook_id, task_id)
56 self.write(json.dumps(submissions))
59class GenerateFeedbackHandler(E2xApiHandler):
60 @web.authenticated
61 @check_xsrf
62 def post(self, assignment_id, student_id):
63 hide_cells = json.loads(self.get_argument("hide_cells", "false"))
64 self.write(
65 json.dumps(
66 self.api.generate_feedback(
67 assignment_id, student_id, hide_cells=hide_cells
68 )
69 )
70 )
73class GenerateAllFeedbackHandler(E2xApiHandler):
74 @web.authenticated
75 @check_xsrf
76 def post(self, assignment_id):
77 hide_cells = json.loads(self.get_argument("hide_cells", "false"))
78 self.write(
79 json.dumps(self.api.generate_feedback(assignment_id, hide_cells=hide_cells))
80 )
83class GraderHandler(E2xApiHandler):
84 @web.authenticated
85 @check_xsrf
86 def get(self):
87 e2xgrader_settings = self.settings.get("e2xgrader", dict())
88 grader_settings = e2xgrader_settings.get("graders", list())
89 self.write(json.dumps(grader_settings))
92class ExportGradesHandler(E2xApiHandler):
93 def initialize(self) -> None:
94 self.__exporter = GradeExporter()
95 self.set_header("Content-Type", 'text/csv; charset="utf-8"')
96 self.set_header("Content-Disposition", "attachment; filename=grades.csv")
98 @web.authenticated
99 @check_xsrf
100 def get(self):
101 level = self.get_argument("level", "notebook")
102 if level == "task":
103 self.__exporter.tasks = True
104 elif level == "assignment":
105 self.__exporter.notebooks = False
106 normalize = self.get_argument("normalize", "false")
107 if normalize.lower() == "max_score":
108 self.__exporter.include_max_score = True
109 else:
110 self.__exporter.normalize = normalize.lower() == "true"
111 self.write(self.__exporter.get_grades().to_csv())
112 self.finish()
115class AnnotationCollectionHandler(E2xApiHandler):
116 @web.authenticated
117 @check_xsrf
118 @check_notebook_dir
119 def get(self):
120 solution_cells = self.api.get_annotations(self.get_argument("submission_id"))
121 if solution_cells is None:
122 raise web.HTTPError(404)
123 return self.write(json.dumps(solution_cells))
126class AnnotationHandler(E2xApiHandler):
127 @web.authenticated
128 @check_xsrf
129 @check_notebook_dir
130 def put(self, solution_cell_id):
131 data = self.get_json_body()
132 solution_cell = self.api.save_annotation(
133 submission_id=data.get("submission_id"),
134 name=data.get("name"),
135 annotation=data.get("annotation"),
136 )
137 if solution_cell is None:
138 raise web.HTTPError(404)
140 self.write(json.dumps(solution_cell))
143default_handlers = [
144 (r"/formgrader/api/assignments", E2xAssignmentCollectionHandler),
145 (r"/formgrader/api/assignment/([^/]+)", E2xAssignmentHandler),
146 (r"/formgrader/api/solution_cells/([^/]+)/([^/]+)", SolutionCellCollectionHandler),
147 (
148 r"/formgrader/api/submitted_tasks/([^/]+)/([^/]+)/([^/]+)",
149 SubmittedTaskCollectionHandler,
150 ),
151 (
152 r"/formgrader/api/assignment/([^/]+)/generate_feedback",
153 GenerateAllFeedbackHandler,
154 ),
155 (
156 r"/formgrader/api/assignment/([^/]+)/([^/]+)/generate_feedback",
157 GenerateFeedbackHandler,
158 ),
159 (
160 r"/formgrader/api/export_grades/?",
161 ExportGradesHandler,
162 ),
163 (r"/formgrader/api/annotations", AnnotationCollectionHandler),
164 (r"/formgrader/api/annotation/([^/]+)", AnnotationHandler),
165]