Coverage for e2xgrader/server_extensions/apps/validate_assignment/validator.py: 77%
30 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
1from typing import List, Union
3from nbformat.notebooknode import NotebookNode
4from nbgrader import utils
5from nbgrader.validator import Validator
7from ....utils.extra_cells import (
8 get_choices,
9 is_attachment_cell,
10 is_extra_cell,
11 is_multiplechoice,
12 is_singlechoice,
13)
16class E2XValidator(Validator):
17 def validate_extra_cell(self, cell: NotebookNode) -> Union[None, float]:
18 if (
19 (is_multiplechoice(cell) or is_singlechoice(cell))
20 and len(get_choices(cell)) < 1
21 ) or (is_attachment_cell(cell) and len(cell.get("attachments", {})) < 1):
22 return 0
24 def code_cell_errored(self, cell: NotebookNode) -> bool:
25 for output in cell.outputs:
26 if (
27 output.output_type == "error"
28 or output.output_type == "stream"
29 and output.name == "stderr"
30 ):
31 return True
32 return False
34 def _get_failed_cells(self, nb: NotebookNode) -> List[NotebookNode]:
35 failed = []
36 for cell in nb.cells:
37 if self._should_skip_cell(cell):
38 continue
40 # if it's a grade cell, the check the grade
41 if utils.is_grade(cell):
42 score, max_score = utils.determine_grade(cell, self.log)
44 if is_extra_cell(cell):
45 score = self.validate_extra_cell(cell)
47 # it's a markdown cell, so we can't do anything
48 if score is not None and score < max_score:
49 failed.append(cell)
50 elif (
51 self.validate_all
52 and cell.cell_type == "code"
53 and self.code_cell_errored(cell)
54 ):
55 failed.append(cell)
57 return failed
59 def _should_skip_cell(self, cell: NotebookNode) -> bool:
60 return not (self.validate_all or utils.is_grade(cell) or utils.is_locked(cell))