forked from ucbds-infra/otter-grader
/
questions.py
81 lines (68 loc) · 2.25 KB
/
questions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
"""
Question configurations for Otter Assign
"""
import copy
import yaml
from .constants import BLOCK_QUOTE, ALLOWED_NAME
from .utils import get_source, lock, get_spec, EmptyCellException
def is_question_cell(cell):
"""
Returns whether cell contains BEGIN QUESTION in a block quote
Args:
cell (``nbformat.NotebookNode``): a notebook cell
Returns:
``bool``: whether the current cell is a question definition cell
"""
if cell.cell_type != 'markdown':
return False
return get_spec(get_source(cell), "question") is not None
def gen_question_cell(cell, manual, need_close_export):
"""
Returns a locked question cell with metadata hidden in an HTML comment
Args:
cell (``nbformat.NotebookNode``): the original question cell
Returns:
``nbformat.NotebookNode``: the updated question cell
"""
cell = copy.deepcopy(cell)
source = get_source(cell)
if manual:
source = ["<!-- BEGIN QUESTION -->", ""] + source
if need_close_export:
source = ["<!-- END QUESTION -->", ""] + source
begin_question_line = get_spec(source, "question")
start = begin_question_line - 1
assert source[start].strip() == BLOCK_QUOTE
end = begin_question_line
while source[end].strip() != BLOCK_QUOTE:
end += 1
source[start] = "<!--"
source[end] = "-->"
cell['source'] = '\n'.join(source)
# check if cell is empty, and if so, throw error
cell_text = source[:start]
try:
cell_text += source[end+1:]
except IndexError:
pass
if not "".join(cell_text).strip():
raise EmptyCellException()
lock(cell)
return cell
def read_question_metadata(cell):
"""
Returns parsed question metadata from a question cell
Args:
cell (``nbformat.NotebookNode``): the question cell
Returns:
``dict``: question metadata
"""
source = get_source(cell)
begin_question_line = get_spec(source, "question")
i, lines = begin_question_line + 1, []
while source[i].strip() != BLOCK_QUOTE:
lines.append(source[i])
i = i + 1
metadata = yaml.full_load('\n'.join(lines))
assert ALLOWED_NAME.match(metadata.get('name', '')), metadata
return metadata