Skip to content

fix/CSV Export#77

Merged
BeWelsh merged 1 commit into
mainfrom
fix/csv-export
Apr 24, 2026
Merged

fix/CSV Export#77
BeWelsh merged 1 commit into
mainfrom
fix/csv-export

Conversation

@jobvengalil
Copy link
Copy Markdown
Collaborator

@jobvengalil jobvengalil commented Apr 24, 2026

Description

The CSV export endpoint was crashing with a 500 error for any schedule that had sections without a time block assigned. The backend's get_rich_sections service sets time_block=None for unassigned sections

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

What Changed?

  • Added a null check for section.time_block in the CSV export loop in backend/app/routers/schedule.py
  • Sections with no time block assigned now export an empty string for the time_block column instead of crashing the request

Testing & Validation

How this was tested

Unfinished Work & Known Issues

  • None, this PR is complete and production-ready

Notes & Nuances

  • The draft guard earlier in the route already prevents exporting incomplete schedules in theory, but sections can legally have time_block=None

Reviewer Notes

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced CSV export reliability for scheduling information. Improved time block field generation to gracefully handle missing or unavailable data through better fallback logic. Exported scheduling files now contain clean, properly-formatted values in all scenarios, eliminating undefined entries and ensuring more complete data output.

@jobvengalil jobvengalil requested a review from BeWelsh April 24, 2026 17:10
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2026

Walkthrough

The CSV export's time_block field generation now explicitly handles None values by outputting an empty string and adds a fallback mechanism that formats section.time_block directly when the time_block_id lookup fails in the enriched data dictionary.

Changes

Cohort / File(s) Summary
CSV Export Time Block Logic
backend/app/routers/schedule.py
Enhanced time_block field generation with explicit None handling and fallback formatting that directly uses section.time_block when enriched data lookup fails.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • AutomatedCourseScheduler#64 — Implements split-block aggregation and CSV export functionality for the same time_block field; this PR adds defensive handling for edge cases in that logic.

Suggested reviewers

  • BeWelsh
  • Saisri24

Poem

🐰 A rabbit's whisper, soft and clear:
When blocks are None, we needn't fear!
A fallback waits, so swift and bright,
Formatting time blocks just right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'fix/CSV Export' is vague and overly generic, using a common prefix pattern without clearly conveying what specific issue is being fixed or why. Use a more descriptive title that specifies the actual problem, such as 'Fix CSV export crash when sections lack assigned time blocks' or 'Handle null time_block values in CSV export'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description covers the core issue and changes but is largely incomplete, missing testing details, screenshots, and proper explanation of design decisions and edge cases.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/csv-export

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/app/routers/schedule.py (1)

185-191: ⚠️ Potential issue | 🔴 Critical

Critical: the same NoneType crash still occurs via time_pref when section.time_block is None.

The fix at lines 162-163 only guards the time_block column. A few lines below, line 187 unconditionally dereferences section.time_block.time_block_id inside the time_pref generator. Whenever a section has instructors but no assigned time block, this will still raise AttributeError: 'NoneType' object has no attribute 'time_block_id' and return HTTP 500 — i.e., the very bug this PR claims to fix is only partially resolved. Note that even with a guard, comparing mp.time_block_id == None is never a useful match, so the correct behavior is to short-circuit time_pref to "" when the section has no time block.

🐛 Proposed fix
-            time_pref = "; ".join(
-                next(
-                    (mp.preference for mp in i.meeting_preferences if mp.time_block_id == section.time_block.time_block_id),
-                    "",
-                )
-                for i in instructors
-            )
+            if section.time_block is None:
+                time_pref = ""
+            else:
+                tb_id = section.time_block.time_block_id
+                time_pref = "; ".join(
+                    next(
+                        (mp.preference for mp in i.meeting_preferences if mp.time_block_id == tb_id),
+                        "",
+                    )
+                    for i in instructors
+                )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/app/routers/schedule.py` around lines 185 - 191, The generator
building time_pref dereferences section.time_block.time_block_id unconditionally
and will crash when section.time_block is None; change the logic in the
time_pref construction (the generator that iterates instructors and checks
mp.time_block_id) to first short‑circuit and return an empty string when
section.time_block is None, otherwise perform the existing lookup against
mp.time_block_id == section.time_block.time_block_id using meeting_preferences
and mp identifiers; reference the time_pref variable, section.time_block, and
meeting_preferences/mp.time_block_id to locate and modify the code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@backend/app/routers/schedule.py`:
- Around line 185-191: The generator building time_pref dereferences
section.time_block.time_block_id unconditionally and will crash when
section.time_block is None; change the logic in the time_pref construction (the
generator that iterates instructors and checks mp.time_block_id) to first
short‑circuit and return an empty string when section.time_block is None,
otherwise perform the existing lookup against mp.time_block_id ==
section.time_block.time_block_id using meeting_preferences and mp identifiers;
reference the time_pref variable, section.time_block, and
meeting_preferences/mp.time_block_id to locate and modify the code.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8b54c588-e162-4295-9056-ebe92f5ca6fa

📥 Commits

Reviewing files that changed from the base of the PR and between 99769d6 and 45c939e.

📒 Files selected for processing (1)
  • backend/app/routers/schedule.py

Copy link
Copy Markdown
Collaborator

@BeWelsh BeWelsh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The final PR

@BeWelsh BeWelsh merged commit 3d99844 into main Apr 24, 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.

2 participants