Skip to content

Fix spurious printing of forecast/scores objects during :=#1163

Open
nikosbosse wants to merge 2 commits intomainfrom
fix/935-spurious-autoprint
Open

Fix spurious printing of forecast/scores objects during :=#1163
nikosbosse wants to merge 2 commits intomainfrom
fix/935-spurious-autoprint

Conversation

@nikosbosse
Copy link
Copy Markdown
Collaborator

CLAUDE:

Summary

  • Fixes forecast and scores objects print output every time a column is changed #935 by leveraging data.table's shouldPrint() mechanism to suppress autoprinting when := modifies forecast or scores objects in place
  • Adds print.scores() method with the same autoprint suppression
  • Skips validation in [.forecast during := operations (the validation was consuming data.table's autoprint suppression flag and triggering the printing side-effect)
  • Bumps data.table dependency from >= 1.16.0 to >= 1.17.0 (which contains the upstream fix in Rdatatable/data.table#6631)

See #1161 for detailed root cause analysis.

How it works

The fix has two layers:

  1. print.forecast() and print.scores(): Check data.table's internal shouldPrint(x) at the top of the method. When := is used, data.table sets a flag to suppress autoprinting. If the flag indicates suppression, return invisible(x) immediately without printing any output (including the forecast header).

  2. [.forecast(): Detect in-place modifications (:=) by checking identical(x, out) && ...length() > 1 and skip validation. Previously, the validation call inside [.forecast would consume the shouldPrint flag before print.forecast could check it.

Breaking change

[.forecast no longer validates during := operations. Users who relied on the warning when := broke a forecast object's contract (e.g., changing predicted to character) will need to call assert_forecast() explicitly. The $<-, [[<-, and [<- assignment methods still validate.

Test plan

  • All 765 existing tests pass
  • New tests verify := produces no output for all forecast types (binary, quantile, point, sample_continuous, sample_discrete)
  • New tests verify := on scores objects produces no output
  • New tests verify multiple sequential := operations produce no output
  • New tests verify explicit print() still works after :=
  • New tests verify x[] force-print still works
  • New tests verify [.forecast validates subsets regardless of size (30-row hack removed)
  • New tests verify print header and data content are shown for explicit prints
  • Existing snapshot tests unchanged

🤖 Generated with Claude Code

Leverage data.table's shouldPrint() mechanism to suppress autoprinting
when := modifies forecast or scores objects in place. Also skip
validation in [.forecast during := operations since the validation was
triggering the autoprint side-effect.

Key changes:
- print.forecast: check shouldPrint() early and return invisible if FALSE
- print.scores: new method with same shouldPrint() check
- [.forecast: detect in-place := modifications and skip validation
- Bump data.table dependency to >= 1.17.0 (contains upstream fix)

Closes #1161

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.99%. Comparing base (4a222da) to head (3b48329).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1163   +/-   ##
=======================================
  Coverage   97.98%   97.99%           
=======================================
  Files          37       37           
  Lines        1984     1992    +8     
=======================================
+ Hits         1944     1952    +8     
  Misses         40       40           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nikosbosse
Copy link
Copy Markdown
Collaborator Author

nikosbosse commented Apr 4, 2026

CLAUDE (and verified by Nikos): Here's a before/after comparison showing the fix in action:

Before (main):

ex <- data.table::copy(example_quantile)
ex[, model := paste(model, "a")]
#> Forecast type: quantile
#> Forecast unit:
#> location, target_end_date, target_type, location_name, forecast_date, model,
#> and horizon
#>
#> Key: <location, target_end_date, target_type>
#>        location target_end_date target_type observed location_name
#>          <char>          <Date>      <char>    <num>        <char>
#>     1:       DE      2021-01-02       Cases   127300       Germany
#>     2:       DE      2021-01-02      Deaths     4534       Germany
#>     3:       DE      2021-01-09       Cases   154922       Germany
#>     4:       DE      2021-01-09      Deaths     6117       Germany
#>     5:       DE      2021-01-16       Cases   110183       Germany
#>    ---
#> 20541:       IT      2021-07-24      Deaths       78         Italy
#> 20542:       IT      2021-07-24      Deaths       78         Italy
#> 20543:       IT      2021-07-24      Deaths       78         Italy
#> 20544:       IT      2021-07-24      Deaths       78         Italy
#> 20545:       IT      2021-07-24      Deaths       78         Italy
#>   ... (full table unexpectedly printed)

The entire 20,545-row forecast object is printed every time a column is modified via :=. This happens for all forecast types and scores objects.

After (fix branch):

ex <- data.table::copy(example_quantile)
ex[, model := paste(model, "a")]
# (no output — matches the behavior of := on a plain data.table)

print(ex)  # explicit print still works as expected
#> Forecast type: quantile
#> Forecast unit:
#> location, target_end_date, target_type, location_name, forecast_date, model,
#> and horizon
#>
#>        location target_end_date target_type observed ...
#>     1:       DE      2021-01-02       Cases   127300 ...
#>    ---
#> 20541:       IT      2021-07-24      Deaths       78 ...

The same fix applies to scores objects and all forecast types (binary, quantile, point, sample_continuous, sample_discrete).

Use expect_gt() instead of expect_true(x > 0) and fixed = TRUE for
static regex patterns in grepl().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

forecast and scores objects print output every time a column is changed

1 participant