# Test (not exported)
from data401_nlp.helpers.submit import parse_answersNotebook Submission Helper (submit.py)
Answer format convention
Student answers are expected to appear in code cells using the following pattern:
q1_answer = "A"
q2_answer = 3.14
q3_answer = ["token", "vector", "embedding"]Where: - Each answer variable name begins with q - The question number follows (q1, q2, …) - The variable is assigned a valid Python literal
This convention allows answers to be reliably extracted from the notebook without requiring special widgets or forms.
Submission workflow
The submission process has three steps:
Collect answers Code cells matching the answer pattern are located and extracted.
Parse answers Extracted code is converted into a structured Python dictionary.
Submit answers The parsed answers are sent via HTTP to a grading service.
Each step is implemented as a separate function to keep the logic clear and testable.
collect_answers
def collect_answers(
show:bool=True, # Print extracted answers
namespace:NoneType=None, # Namespace to search (defaults to globals())
dname:NoneType=None, # Dialog name (dialoghelper only)
path:NoneType=None, # Notebook path (local fallback only)
): # [('code', 'q1_answer = ...'), ...]
Collect student answers.
Priority: 1. Live Python variable state (default, works everywhere) 2. dialoghelper (optional, Solveit) 3. Notebook file parsing (local Jupyter only, requires path)
parse_answers
def parse_answers(
raw, # Output from `collect_answers`, containing raw code strings.
): # Mapping from answer variable name (e.g. 'q1_answer') to its value.
Parse extracted answer code into a dictionary.
submit_answers
def submit_answers(
student_id, answers:NoneType=None, raw_answers:NoneType=None, dname:NoneType=None, path:NoneType=None,
url:str='https://nbsubmit-production.up.railway.app', api_key:NoneType=None, verbose:bool=True
):
Call self as a function.
review_answers
def review_answers(
namespace:NoneType=None, # Namespace to search (defaults to globals())
dname:NoneType=None, # Dialog name (Solveit / Deepnote)
path:NoneType=None, # Notebook path (local fallback only)
show:bool=True, # Print formatted output.
): # Parsed answers ready for submission.
Review extracted student answers WITHOUT submitting.
Priority: 1. Live variable state 2. dialoghelper (optional) 3. Notebook parsing (local only, requires path)
raw = [
("code", 'q1_answer = "A"'),
("code", "q2_answer = 42"),
]
assert parse_answers(raw) == {
"q1_answer": "A",
"q2_answer": 42,
}
print("parse_answers OK")parse_answers OK