Problem
Exercise.DONE_MARKER is defined in pythonlings/core/exercise.py, but the marker string is still written out literally in a few places:
pythonlings/core/exercise.py:20 — DONE_MARKER = "# I AM NOT DONE" (the constant)
pythonlings/cli.py:256 — hardcoded in the "marker still present" error message
pythonlings/widgets/output_panel.py:104 — hardcoded in "Remove the # I AM NOT DONE line to advance."
pythonlings/screens/welcome.py:19 — hardcoded in the welcome instructions
So the marker exists in three copies that are only kept in sync by convention. If the marker ever changes (e.g. a (v2) suffix to migrate the curriculum), the runner will recognize the new marker while the error/welcome copy still tells learners to look for the old one. Nothing fails loudly — the tests would stay green while learners get misleading instructions.
Proposed Behavior
Reference the constant instead of the literal in those three spots, e.g.:
f"pythonlings: tests pass but the {Exercise.DONE_MARKER!r} marker is still in {name}.\n"
and the equivalent for the welcome and output-panel copy. Keeps the user-visible text in sync with what the runner actually checks, at no behavioral change.
Alternatives Considered
- Leave as-is: works today, but it's exactly the kind of string coupling that quietly breaks on the next marker change.
- Move the copy strings next to the constant as well: more thorough, but the three messages are in different screens anyway, so referencing the constant is enough.
Problem
Exercise.DONE_MARKERis defined inpythonlings/core/exercise.py, but the marker string is still written out literally in a few places:pythonlings/core/exercise.py:20—DONE_MARKER = "# I AM NOT DONE"(the constant)pythonlings/cli.py:256— hardcoded in the "marker still present" error messagepythonlings/widgets/output_panel.py:104— hardcoded in "Remove the # I AM NOT DONE line to advance."pythonlings/screens/welcome.py:19— hardcoded in the welcome instructionsSo the marker exists in three copies that are only kept in sync by convention. If the marker ever changes (e.g. a
(v2)suffix to migrate the curriculum), the runner will recognize the new marker while the error/welcome copy still tells learners to look for the old one. Nothing fails loudly — the tests would stay green while learners get misleading instructions.Proposed Behavior
Reference the constant instead of the literal in those three spots, e.g.:
f"pythonlings: tests pass but the {Exercise.DONE_MARKER!r} marker is still in {name}.\n"and the equivalent for the welcome and output-panel copy. Keeps the user-visible text in sync with what the runner actually checks, at no behavioral change.
Alternatives Considered