Cells¶
Solution stripping, marker validation, grading cell injection, and notebook post-processing.
mograder.grading.cells
¶
Notebook cell manipulation: marker validation, solution stripping, grading cell injection, and mark/feedback parsing.
validate_markers(lines, filepath)
¶
Check that all solution and hidden-test markers are properly paired.
Returns a list of error messages (empty if valid).
Source code in src/mograder/grading/cells.py
strip_solutions(lines)
¶
Remove solution blocks from source lines.
Lines between BEGIN SOLUTION / END SOLUTION are replaced with
# YOUR CODE HERE and pass at the correct indentation.
The pass ensures empty function bodies remain syntactically valid.
When a return statement after END SOLUTION references simple
variable names that are only defined inside the removed solution block,
sentinel assignments (name = ...) are inserted before the
placeholder so the return does not raise :class:NameError.
Source code in src/mograder/grading/cells.py
count_markers(lines)
¶
count_hidden_markers(lines)
¶
strip_hidden_tests(lines)
¶
Remove hidden test blocks from source lines.
Lines between BEGIN HIDDEN TESTS / END HIDDEN TESTS are replaced with
a single # HIDDEN TESTS placeholder comment at the correct indentation.
Source code in src/mograder/grading/cells.py
extract_hidden_tests(lines)
¶
Extract hidden test blocks as (indent, lines) tuples.
Each tuple contains the indentation prefix and the list of lines (with their original indentation) from one hidden-test block. Used during autograde to reinject hidden tests into submitted notebooks.
Source code in src/mograder/grading/cells.py
convert_markdown_cells(lines)
¶
Convert stripped markdown answer cells to editable mo.md() blocks.
After strip_solutions(), markdown answer cells look like::
response_text = "placeholder text"
# YOUR CODE HERE
pass
mo.md(response_text)
This function converts them to::
mo.md(r\"\"\"
placeholder text
\"\"\")
so that students see a clean editable markdown cell instead of ugly placeholder code.
Source code in src/mograder/grading/cells.py
build_submit_cell(server_url, assignment_name)
¶
Build a submit cell that uses mograder.remote.submit().
Returns source text for two marimo cells (username input + submit action).
Source code in src/mograder/grading/cells.py
strip_submit_cells(text)
¶
Remove the submit cell pair injected by :func:build_submit_cell.
The submit cell uses mo.ui.run_button which makes marimo export
wait indefinitely for a click in headless mode. Grader snapshots in
submitted/ must therefore not contain it.
Returns text unchanged if no submit cell is present.
Source code in src/mograder/grading/cells.py
read_notebook_type(text)
¶
Read mograder-type from a PEP 723 script block.
Returns "lecture", "assignment", etc. Defaults to
"assignment" when no metadata is found.
Source code in src/mograder/grading/cells.py
strip_layout_metadata(lines)
¶
Remove layout_file and html_head_file kwargs from marimo.App(...).
Handles both single-line and multi-line App() calls. Preserves
other keyword arguments (width, app_title, etc.).
Source code in src/mograder/grading/cells.py
rewrite_notebook_links(lines)
¶
Rewrite inter-notebook links for hub deployment.
- Lecture links
[text](../Name/Name.py)where Name starts withLbecome[text](/run/Name/) - Assignment links
[text](../Name/Name.py)where Name starts withAare stripped to plain text: justtext
Source code in src/mograder/grading/cells.py
process_file(source, output_dir, dry_run=False, validate_only=False, submit_url=None)
¶
Process a single notebook file. Returns True on success.
Source code in src/mograder/grading/cells.py
build_release_zip(release_dir)
¶
Create a zip of student-facing release files, excluding artifacts.
Returns None (and removes any stale zip) when the directory contains only a single file — a zip that wraps one file adds no value.
Uses a fixed timestamp so the zip is reproducible across runs.
Source code in src/mograder/grading/cells.py
extract_marking_scale(source_lines)
¶
Extract the Marking Scale admonition from a source notebook.
Looks for /// details | Marking Scale ... /// block in markdown cells.
Returns the markdown content (without the admonition wrapper), or None.
Source code in src/mograder/grading/cells.py
parse_marks_metadata(source_lines)
¶
Extract marks metadata from a notebook.
Reads _marks = {...} from the MARKS_MARKER cell. All question marks
(both auto-checked and manual) must be listed in this single dict.
Returns None if no MARKS_MARKER cell found.
Source code in src/mograder/grading/cells.py
parse_auto_marks(source_lines)
¶
Extract auto-scored marks from a verification cell with marks data.
Looks for _mograder_marks and _mograder_checks in the verification
cell and computes sum of marks for PASS checks. Supports both 4-tuple
format (label, status, earned_weight, total_weight) (fractional) and
legacy 2-tuple format (label, status) (binary).
Returns None if no marks data found in the verification cell.
Source code in src/mograder/grading/cells.py
has_grading_cells(source_lines)
¶
Detect if grading cells are already injected.
inject_grading_cells(source_lines, checks, cell_errors=0, marks=None, source_check_keys=None)
¶
Insert verification summary + marker feedback cells before if __name__.
Returns modified source lines. Idempotent: if grading cells already exist, returns the input unchanged.
When marks is provided, the verification cell includes a marks column
and the feedback cell is pre-configured for manual-only grading.
source_check_keys, if given, determines which marks-dict keys are
auto-graded (have a check() call in the source notebook). When omitted,
keys are inferred from the student's executed checks — which may be
incomplete if mo.stop guards prevented some checks from running.
Source code in src/mograder/grading/cells.py
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 | |
parse_marker_feedback(source_lines)
¶
Extract _mark and _feedback from a graded notebook.
Looks for the MOGRADER: MARKER FEEDBACK marker and parses the variable assignments that follow it.
Returns (mark, feedback) where mark is None if not yet graded.
Source code in src/mograder/grading/cells.py
write_marker_feedback(file_path, mark, feedback)
¶
Write _mark and _feedback values into a graded notebook.
The file must contain a MOGRADER: MARKER FEEDBACK marker cell.
Always writes _feedback as a triple-quoted string.
Raises ValueError if the feedback marker is not found.