Skip to content

fix(prep): rebuild corrected data when prep steps change - #314

Open
iabaako wants to merge 3 commits into
refactor/310-action-strenumfrom
fix/297-replay-corrections-on-prep
Open

iabaako wants to merge 3 commits into
refactor/310-action-strenumfrom
fix/297-replay-corrections-on-prep

Conversation

@iabaako

@iabaako iabaako commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Pull Request Summary 🚀

What does this PR do? 📝

Closes #297. When a dataset's prep data changes, its corrected table is now rebuilt from the new prep output by replaying the correction log. This only happens if the dataset already has a corrected table.

The rebuild runs after:

  • a prep step is added or removed (new);
  • a project bundle re-seeds a dataset's prep steps but brings no corrections for it (new);
  • a raw dataset is re-imported (existing, now uses the same check).

Replay failures, and errors from the rebuild itself, are shown on the Prep page.

Why is this change needed? 🤔

Check pages read corrected.duckdb before prep. Until now, changing a prep step never touched corrected. After you dropped a column in Prep, check pages kept showing the old corrected table.

How was this implemented? 🛠️

 prep_add_step / _remove_prep_step              (views/prep_view.py)
   prep_apply_action
+  queue_notice(success)
+  _refresh_corrected_data
+    CorrectionProcessor.refresh_existing_corrected_data
+      if corrected table exists: _reapply_all_corrections
+    queue_notice(warning | error)
   st.rerun()

 Prep tab render
+  show_queued_notices(prep_<alias>)
  • CorrectionProcessor.refresh_existing_corrected_data (processing/corrections.py): replays the correction log only when a corrected table exists. The Prep page, the import refresh and bundle application all use it. Replay still goes through _apply_correction_row, so accept rows are skipped and acceptances whose values changed become inactive (from Corrections: add source and accept to the log, extract a shared correction form #296).
  • queue_notice / show_queued_notices (utils/ui_utils.py): both prep handlers end in st.rerun(), which cleared messages rendered just before it. Messages are now queued in session state and shown once on the next run, under "Apply Changes". This also fixes an existing bug where the prep-step failure warning on removal never appeared. CONTRIBUTING.md now documents the helper.
  • Error boundary: if the rebuild fails, for example on a storage error, the page logs it and shows an error. The prep change is already saved at that point.
  • Bundles (utils/project_config.py): _apply_corrections seeds and replays bundled corrections as before. It also refreshes existing corrected tables for re-prepped datasets that the bundle has no corrections for.
  • Not covered: editing a prep step. There is no code path for it, so that part of the acceptance criteria is N/A.
  • Out of scope: the Corrections page has the same problem of messages being cleared by a rerun. That's left for a follow-up that can use the same helper.

Merge danger

Door: two-way. No schemas, stored formats or migrations change. The only new session-state key is st_queued_notices.

Blast radius: corrected data. After this merges, corrected tables are rebuilt more often, and a correction that no longer applies to the new prep output is marked Failed in the correction log instead of silently serving stale data.

How to test or reproduce ? 🧪

  1. Import a dataset, add a prep step, and apply one correction on the Corrections page.
  2. Go back to Prep and add a "remove column(s)" step for a column that isn't corrected. Open a check page: the column is gone and the correction is still applied.
  3. Remove a column that a correction modifies. The Prep page shows the success message plus a warning that the correction could not be reapplied. On the Corrections page, the log marks it Failed.
  4. Repeat with a dataset that has never been corrected: no corrected table is created.

Tests:

  • Before, on refactor/310-action-strenum: the new tests fail. refresh_existing_corrected_data, queue_notice and format_reapply_failures don't exist, and no rebuild runs after a prep change.
  • After: just test gives 3364 passed and 6 skipped. New coverage:
    • TestRefreshExistingCorrectedData: no-op without a corrected table, rebuild from new prep, failures reported.
    • TestPrepChangeRefreshesCorrectedData: add and remove trigger the rebuild, a rejected step doesn't, and success, warning and error messages appear after the rerun.
    • TestQueuedNotices: messages show in order, once, per scope.
    • Bundle test: re-seeded prep without corrections refreshes the existing corrected table.

Screenshots (if applicable) 📷

Screenshot 2026-10-01 093630 Screenshot 2026-10-01 093658

Checklist ✅

  • I have run and tested my changes locally
  • I have limit this PR to less than 1000 lines of code change (if not, explain why). The diff is +569/−35, of which +201/−21 is source and docs.
  • I have updated/added tests to cover my changes (if applicable)
  • I have updated/added requirements to cover my changes (if applicable). N/A, no new dependencies.
  • I have run linting and formatting on any code changes (if applicable). just pre-commit-run passes.
  • I have updated the documentation (README, etc.) accordingly: docs/ARCHITECTURE.md data flow and the CONTRIBUTING.md view UI rules.
  • I have reviewed and resolved any merge conflict

Reviewer Emoji Legend

:code: Meaning
😃👍💯 :smiley: :+1: :100: I like this...

...and I want the author to know it! This is a way to highlight positive parts of a code review.
⭐⭐⭐ :star: :star: :star: Important to fix before PR can be approved...

And I am providing reasons why it needs to be addressed as well as suggested improvements.
⭐⭐ :star: :star: Important to fix but non-blocking for PR approval...

And I am providing suggestions where it could be improved either in this PR or later.
⭐ :star: Give this some thought but non-blocking for PR approval...

...and consider this a suggestion, not a requirement.
❓ :question: I have a question.

This should be a fully formed question with sufficient information and context that requires a response.
📝 :memo: This is an explanatory note, fun fact, or relevant commentary that does not require any action.
⛏ :pick: This is a nitpick.

This does not require any changes and is often better left unsaid. This may include stylistic, formatting, or organization suggestions and should likely be prevented/enforced by linting if they really matter
♻️ :recycle: Suggestion for refactoring.

Should include enough context to be actionable and not be considered a nitpick.

🤖 Generated with Claude Code

iabaako and others added 2 commits October 1, 2026 09:05
Adding or removing a prep step now rebuilds the alias's corrected table
from the new prep output by replaying the correction log, but only when a
corrected table already exists. The import refresh shares the same check
through CorrectionProcessor.refresh_existing_corrected_data.

Both prep handlers end in a rerun, which wiped any warning rendered
straight away, so prep and correction reapply failures are now queued in
session state and shown on the next run of the Prep page.

Closes #297

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Act on review of the corrected-data refresh:

- Add queue_notice/show_queued_notices to ui_utils so success, warning
  and error messages raised before st.rerun() are shown on the next run.
  The Prep page uses it for step added/removed messages and reapply
  failures, replacing its private tuple queue.
- Catch and report a failed corrected-data rebuild on the Prep page
  (UI boundary) instead of crashing after the prep change was saved.
- Applying a project bundle now also rebuilds an existing corrected
  table for aliases whose prep steps it re-seeds without corrections.
- Extract format_reapply_failures, cut the extra delegation in
  refresh_existing_corrected_data, use "refresh" naming in prep_view,
  and share mock setup in the prep view tests.

Refs #297

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@iabaako
iabaako requested a review from a team as a code owner October 1, 2026 09:17
@iabaako
iabaako added this pull request to stack #313 October 1, 2026 09:42
@iabaako
iabaako requested a balanced review from Copilot October 1, 2026 09:42
Comment thread tests/views/test_prep_view.py Fixed
Comment thread tests/views/test_prep_view.py Fixed
Comment thread tests/views/test_prep_view.py Fixed
Comment thread tests/views/test_prep_view.py Fixed
Comment thread tests/views/test_prep_view.py Fixed
Comment thread tests/views/test_prep_view.py Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Zero-row prep results can bypass queued notices and cause check pages to fall back to stale raw data.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

Rebuilds corrected datasets after prep changes to prevent stale check results.

Changes:

  • Adds conditional correction replay after prep changes, imports, and bundle application.
  • Queues Streamlit notices across reruns.
  • Adds regression tests and documentation.
File Description
src/​datasure/​processing/​corrections.py Adds conditional corrected-data refresh.
src/​datasure/​views/​prep_view.py Refreshes corrections after prep changes.
src/​datasure/​views/​import_view.py Reuses conditional refresh after imports.
src/​datasure/​utils/​project_config.py Refreshes corrected data during bundle application.
src/​datasure/​utils/​ui_utils.py Adds rerun-safe notice queueing.
src/​datasure/​utils/​reapply_utils.py Extracts failure-message formatting.
tests/​processing/​test_corrections.py Tests conditional correction refresh.
tests/​views/​test_prep_view.py Tests prep refresh and notices.
tests/​views/​test_import_view.py Tests import-triggered replay.
tests/​utils/​test_project_config.py Tests bundle-triggered replay.
tests/​utils/​test_ui_utils.py Tests queued notices.
tests/​utils/​test_reapply_utils.py Tests failure formatting.
docs/​ARCHITECTURE.md Documents corrected-data rebuilding.
CONTRIBUTING.md Documents rerun-safe notices.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/datasure/processing/corrections.py
Comment thread src/datasure/views/prep_view.py Outdated
A step that removes every row sends the Prep tab down its "No data
available" path, which skipped show_queued_notices, so the step's
success, reapply warnings and rebuild errors were never shown and
resurfaced later. Render them before the empty check.

Also import prep_view once in its tests (as pv) instead of mixing
module and from-imports, per GitHub Code Quality.

Refs #297

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Oct 1, 2026

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The implementation consistently refreshes existing corrected data, reports failures, and includes targeted coverage for all introduced paths.

Review effort: Balanced
Findings: None

Resolved since last review (2)

This branch has not been deployed

No deployments
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.

Corrected data goes stale when prep steps change

2 participants