Avoid instructor grading counting as late with LTI 1.3 - #1347
Avoid instructor grading counting as late with LTI 1.3#1347ascholerChemeketa wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adjusts LTI 1.3 score-push timestamps so instructor-initiated grade pushes don’t get marked late by LMS policies by setting submission.submittedAt to just before the assignment deadline (while leaving student-triggered behavior unchanged).
Changes:
- Add an
instructorTriggeredflag through grading/LTI pathways and use it to computesubmission.submittedAt(deadline - 1 minute when a due date exists). - Extend LTI score payloads with a
submission.submittedAtclaim and refactor timestamp formatting into a helper. - Add/adjust tests to assert the new
submittedAtbehavior and that the flag is forwarded through regrade helpers; fix a missingraiseofHTTPException.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/components/rsptx/lti1p3/test_score_updates.py | Adds coverage for submission.submittedAt behavior for instructor- vs student-triggered pushes. |
| test/components/rsptx/grading_helpers/test_regrade_batch.py | Verifies instructorTriggered forwarding into LTI update calls. |
| components/rsptx/lti1p3/core.py | Implements submittedAt selection logic and threads instructorTriggered through LTI score push APIs. |
| components/rsptx/grading_helpers/regrade.py | Threads instructorTriggered through recompute/regrade flows into LTI score updates. |
| bases/rsptx/web2py_server/applications/runestone/modules/rs_grading.py | Adds instructorTriggered plumbing when sending a single LTI grade from web2py. |
| bases/rsptx/web2py_server/applications/runestone/controllers/assignments.py | Marks manual “send assignment score via LTI” as instructor-triggered. |
| bases/rsptx/web2py_server/applications/runestone/controllers/admin.py | Marks “release grades” / “push LTI grades” as instructor-triggered for LTI 1.3. |
| bases/rsptx/rsmanage/core.py | Marks fixtotals LTI pushes as instructor-triggered. |
| bases/rsptx/assignment_server_api/routers/grader.py | Marks multiple instructor actions (recompute/regrade/manual totals) as instructor-triggered for LTI pushes. |
| bases/rsptx/admin_server_api/routers/lti1p3.py | Fixes missing raise when constructing an HTTPException. |
Suppressed comments (1)
components/rsptx/lti1p3/core.py:128
- This PR aims to treat instructor-initiated grade pushes as on-time by setting
submission.submittedAtjust before the deadline, but at least one instructor-triggered path still callsattempt_lti1p3_score_updates(...)withoutinstructorTriggered=True(e.g.bases/rsptx/assignment_server_api/routers/peer.py:1426,send_lti_scores, which is instructor-only). That path will continue to sendsubmittedAtastimestamp, potentially still counting as late.
async def attempt_lti1p3_score_updates(
rs_assign_id: int, force: bool = False, instructorTriggered: bool = False
):
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| .set_grading_progress("FullyGraded") | ||
| .set_extra_claims({"submission": {"submittedAt": submitted_at}}) | ||
| ) | ||
| print(f"-----------Grade to be sent: {g.__dict__}") |
| async def attempt_lti1p3_score_update( | ||
| rs_user_id: int, rs_assign_id: int, score: float, force: bool = False | ||
| rs_user_id: int, | ||
| rs_assign_id: int, | ||
| score: float, | ||
| force: bool = False, | ||
| instructorTriggered: bool = False, | ||
| ): |
There was a problem hiding this comment.
Fixed across all files
0328ded to
c74e0b1
Compare
|
New force push - fixed the suggestions from initial push and rebased to main after removal of web2py. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
test/components/rsptx/lti1p3/test_score_updates.py:57
- In pylti1p3,
Grade.get_value()is commonly a Python dict (serialized structure), not a JSON string;json.loads(...)will then raise aTypeError. Consider appendinggrade.get_value()directly, or handling both cases (if it's a string thenjson.loads, else use as-is) so the test helper matches the library behavior.
if return_payloads:
sent.append(json.loads(grade.get_value()))
| c, | ||
| a, | ||
| sids, | ||
| dry_run=dry_run, | ||
| only_existing=not create_missing, | ||
| instructorTriggered=True, | ||
| ) |
This sets instructor generated generated grade events to report a submitted time of one minute before the deadline.
Assignments with no due date, and student generated events, continue to use the current time.