1199: Error when as_forecast_<type>() renaming would create duplicate columns - #1212
1199: Error when as_forecast_<type>() renaming would create duplicate columns#1212nikosbosse wants to merge 2 commits into
Conversation
…1199) as_forecast_generic() called setnames() without checking whether a rename target already existed as a column in the data. Renaming e.g. predicted = "prob" while a stale `predicted` column was present created a forecast object with two `predicted` columns that passed validation and was scored on the wrong column. - as_forecast_generic() now errors with a clear message when a rename would collide with an existing column that is not itself being renamed away. Identity renames and simultaneous swaps still work. - assert_forecast_generic() now rejects data with duplicate column names, so corrupt objects from any other construction route fail validation instead of passing silently. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1212 +/- ##
==========================================
+ Coverage 98.15% 98.17% +0.01%
==========================================
Files 41 41
Lines 2225 2244 +19
==========================================
+ Hits 2184 2203 +19
Misses 41 41 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Automated review (Claude Fable, directed by @nikosbosse): Verdict: approve. Verified independently in an isolated checkout of the branch (7a93d80):
Minor (non-blocking): the collision error names only the target column (e.g. No must-fix findings. |
|
We're now enforcing unique column names, which is a slight behaviour change, but I think it's a good one |
The collision error in as_forecast_generic() previously named only the rename target (e.g. "predicted"), not the source column being renamed. It now names both, e.g.: Cannot rename column "prob" to "predicted": a column with this name already exists in the data. Pluralisation via cli is preserved for multiple collisions, and tests now assert that both the source and target column names appear in the message, including a multi-collision (plural) case. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Follow-up (Claude Fable, directed by @nikosbosse): addressed the review's minor finding — the rename collision error in Before:
After:
Pluralisation via cli is preserved for multiple simultaneous collisions ('Cannot rename columns "obs2" and "pred2" to "observed" and "predicted": columns with these names already exist in the data.'), and the tests now assert that both the source and target names appear in the message, including a new multi-collision case. Verified: Commit: 2bbbe8e |
Description
This PR closes #1199.
as_forecast_generic()calleddata.table::setnames()without checking whether a rename target already existed as a column in the data. Calling e.g.as_forecast_binary(dt, predicted = "prob")while a stalepredictedcolumn was present silently created a forecast object with twopredictedcolumns. That object passedassert_forecast()and was then scored on the wrong (stale) column, producing silently wrong scores. All eightas_forecast_<type>()constructors route through this function.The fix (per the settled maintainer decision — error, no silent overwrite, no deprecation period):
as_forecast_generic()now errors with a clearcli_abort()message when a rename would collide with an existing column that is not itself being renamed away. Identity renames (observed = "observed") and simultaneous swaps of renameable columns still work.assert_forecast_generic()now rejects data with duplicate column names, so corrupt objects reached by any other construction route fail validation instead of passing silently.Tests were written first and failed against the unfixed code:
With the fix, the affected test files and the full test suite pass (0 failed, 910 passed, 0 skipped).
Dev note: bug identified by an LLM audit (#1189); fix and tests implemented with LLM support, directed by @nikosbosse.
Checklist
@importFromroxygen tag was added;devtools::document()produced no changes toman/orNAMESPACE).lintron the changed files; no new lints were introduced.