Skip to content

Add --send-all flag for bulk-sending after a recent dry-run#90

Merged
sgeinitz merged 2 commits into
mainfrom
feature/send-all-flag
May 14, 2026
Merged

Add --send-all flag for bulk-sending after a recent dry-run#90
sgeinitz merged 2 commits into
mainfrom
feature/send-all-flag

Conversation

@sgeinitz

Copy link
Copy Markdown
Owner

Summary

  • Adds a --send-all / -s flag to the four tasks that loop and prompt [y/N] per student: send-quiz-reminder (single + --all), send-follow-up-question, send-follow-up-assessments. After a clean --dry-run the second pass is just rote keystrokes; this flag skips the prompt.
  • Guardrails: --send-all is rejected when combined with --dry-run, and only honored if a --dry-run of the same task wrote its dated *_dryrun_*.csv manifest in the last 10 minutes (forces the instructor to inspect the preview first).
  • send-follow-up-assessments --dry-run previously wrote nothing; it now also drops a small *_assessments_sent_dryrun_YYYYMMDD.csv so the recency check has an mtime anchor consistent with the other affected tasks.
  • Drive-by: hardened canvigator_digest._summarizeFollowupThemes against a NaN/empty question_mode cell (NaN is truthy, so the old (... or 'explain').lower() would AttributeError on a hand-edited assessments CSV instead of falling back).

Test plan

  • flake8 clean on both passes
  • pytest — 294/294 pass (9 new tests: recency helper, _interactiveSend with/without send_all, _sendOneAssessment with send_all, conflict guard via subprocess for long + short forms, plus 3 NaN-mode digest tests)
  • python canvigator.py send-follow-up-assessments --help shows -s, --send-all and the new example
  • python canvigator.py --dry-run --send-all send-follow-up-assessments exits non-zero with a clear error
  • Happy path tested live against a real Canvas course: --dry-run then --send-all within 10 minutes — no per-student prompt, all unsent rows post and flip to sent_assessment=1, persistent CSV updated

🤖 Generated with Claude Code

sgeinitz and others added 2 commits May 14, 2026 12:42
A hand-edited *_followup_assessments.csv row with an empty
question_mode cell parses as NaN via pd.read_csv. NaN is truthy in
Python, so `(rows[0].get('question_mode') or 'explain').lower()`
would call `.lower()` on a float and raise AttributeError instead
of falling back. Guard explicitly via pd.isna + a non-empty-string
check, then default to 'explain'.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@sgeinitz sgeinitz merged commit 9c30950 into main May 14, 2026
2 checks passed
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