Skip to content

Report missing student functions as NOT_FOUND - #33

Draft
eliotwrobson wants to merge 1 commit into
mainfrom
claude/function-not-found
Draft

eliotwrobson wants to merge 1 commit into
mainfrom
claude/function-not-found

Conversation

@eliotwrobson

Copy link
Copy Markdown
Collaborator

Problem

FunctionStatusCode.NOT_FOUND existed, and query_function handled it, but the runner never sent it. The lookup sat inside the same try as the call, so a missing function came back as exception with KeyError: 'foo', and assert_fn_equal showed a traceback into the grader's own _student_code_runner.py.

Changes

  • The runner looks the function up separately from calling it. A missing function now returns NOT_FOUND with all the usual fields, exception_name NameError, exception_message Function 'foo' wasn't found in the student code, and no traceback.
  • query_function, and so assert_fn_equal and assert_fn_approx_equal, raises a NameError with exactly that message. I removed the Query for function 'foo' failed: prefix, which would have read awkwardly.
  • Only the lookup can produce NOT_FOUND. A KeyError, AttributeError, ImportError or NameError raised while the function runs stays exception with its normal details.

Workspace mode:

  • A missing module, submodule or attribute is NOT_FOUND.
  • A student module that exists but fails while loading is exception. This covers a bad import inside it, and any other error it raises while loading. Calling that "not found" would hide the error the student needs to see.

Behaviour change for test authors: a test checking response["status"] == "exception" for a missing function now needs "not_found". Tests checking exception_name == "KeyError" need updating too.

Unchanged:

  • A name that exists but isn't callable, such as foo = 5, stays exception with TypeError: 'int' object is not callable. Its traceback still points at the grader's _student_code_runner.py, so that's a possible follow-up.
  • sandbox.query in workspace mode still treats a student module's own ImportError or AttributeError as not found, based on reading the code.

I updated the expected messages in test_stdout_feature and test_quiz_2_1, which asserted the old wording for missing functions. quick_start.md now describes not_found.

Testing

  • New test_function_not_found and test_workspace_function_not_found scenarios. Both fail on main.
  • uv run pytest tests -p no:prairielearn-grader on Python 3.14: all 75 passed on two runs.
  • uv run mypy --config-file pyproject.toml src tests, the command CI runs, is clean. ruff check shows nothing new.
  • Full image built from this branch's docker/ files, with this branch's wheel installed over PyPI 1.1.2. I confirmed its installed _student_code_runner.py and fixture.py match the branch.
  • Graded in that image with the real entrypoint, as ag, using PrairieLearn's MarkovChains-Intro test_student.py and leading_code.py with notebooks based on Markov-Chains-1.ipynb:
Notebook Score Feedback on this branch Feedback on published 1.1.2
Correct 1.0 None Not run
Unchanged starter code 0.0 ...is inaccurate Not run
Function misnamed 0.0 The return value from your function power_iteration: NameError: Function 'power_iteration' wasn't found in the student code ...: KeyError: 'power_iteration'
#grade line deleted 0.0 Same as misnamed Same as misnamed

The message is repeated for the question's second test case. With the tag deleted, the student's function does exist but isn't in a graded cell, so the message says it wasn't found without mentioning the tag.

🤖 Generated with Claude Code

FunctionStatusCode.NOT_FOUND existed but the runner never sent it, so a missing
function came back as an exception with KeyError and a traceback into the
grader's own code.

The runner now looks the function up separately from calling it, so only the
lookup can produce NOT_FOUND. An error raised while the function runs stays an
exception, even a KeyError or ImportError. In workspace mode, a missing module or
attribute is NOT_FOUND, but a student module that exists and fails while loading
is an exception, because hiding its real error wouldn't help anyone.

query_function raises a NameError with the same message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant