Repository navigation
Conversation
get_course_users wrapped its scrape in `except Exception: return None`, so any
parsing failure surfaced only as `TypeError: 'NoneType' object is not iterable`
at the caller's loop, with no indication of what actually went wrong. Its
annotated return type is `list[Member]`, so let the exception propagate instead.
Three roster rows could reach that path, all of them non-student members:
- `user_id` is read from the js-rosterName button's `data-url`. The button is
guarded for None but `data-url` itself is not, so a row carrying the button
without that attribute raised AttributeError on `data_url.split(...)`.
- the submissions count cell is blank for members who cannot submit
(instructors, TAs, readers), so `int(cell.text)` raised ValueError.
- `id_to_role[...]` raised KeyError for any role id outside {0,1,2,3}.
Each now degrades for that one member -- `user_id=None`, `num_submissions=0`,
or the raw role id passed through -- rather than taking down the whole roster.
Adds offline parser tests covering student rows, staff rows, a name button with
no data-url, an unrecognised role id, and a mixed roster; these need no
Gradescope credentials.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Author
|
For the record, Claude Opus wrote these fixes, and I didn't inspect them carefully, but they do appear to fix the error I was encountering. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Account.get_course_userswraps its scrape in:Its annotated return type is
list[Member], so on any parse failure a caller sees only:at their own
for member in membersloop, with nothing pointing at the real cause. I hit this on a course roster and it took a while to work out that the error was in the scrape, not the loop.Cause
Three spots in
get_course_membersassume every roster row is a student. On a course with instructors, TAs or readers, each raises and is then swallowed:data_url.split("user_id=")data-urlis present whenever thejs-rosterNamebutton isAttributeErrorint(cells[num_submissions_column].text)ValueErrorid_to_role[...]data-roleis always in{0,1,2,3}KeyErrorThe first is the narrowest: the button is already guarded for
None, but the attribute read.get("data-url", None)is not, so a name button without that attribute goes straight into.split().The second and third are the common ones — a blank submissions cell for anyone who cannot submit takes down the entire roster, not just that row.
Fix
get_course_usersno longer swallows exceptions, matching its declared return type. Genuine failures (auth, 404, markup changes) now surface where they happen.user_idstaysNonewhen there is nodata-url, which is what the field's own comment already documents: "only present for 'student' accounts in a course".0.Each now degrades for the single member it concerns instead of discarding every member.
Tests
tests/test_course_members.pyparses fixture HTML directly, so unlike the rest of the suite it needs noGRADESCOPE_CI_*credentials and runs in CI as-is. It covers a student row, a staff row with a blank submissions cell, a name button with nodata-url, an unrecognised role id, and a mixed roster.Against
mainfour of the five fail (ValueError,AttributeError,KeyError); all five pass with this change. The student-row case passes both ways, confirming student parsing is unchanged.I could not run the credentialed suite, having no CI accounts — it reports 33 failed / 3 passed identically on
mainand on this branch, every failure beingValueError: Invalid credentials.