Skip to content

check_plugin.py "empty warn" is a false positive for every scrolling plugin — 60 of 76 warnings on a 44-plugin rig are wrong #527

Description

@ChuckBuilds

Summary

check_plugin.py's "empty warn: drew nothing but display() returned X, so the mode is not skipped" fires on a single frame, rendered with force_clear=True, under a frozen clock. All three of those defeat a scrolling plugin, whose first frame is legitimately blank while the content scrolls in. Across the 44 plugins installed on this rig, 60 of the 76 warnings — 79% — are false positives.

A warning that's wrong four times out of five is one people learn to scroll past, which is a problem because the 16 real ones matter (see ChuckBuilds/ledmatrix-plugins#456).

The three causes

1. One frame only.harness._render_size calls _render_mode(inst, mode) exactly once per (size, mode).

2. force_clear=True on every call.harness.py:142-161:

def_render_mode(plugin_instance: Any, mode: str) ->Any:
sig=inspect.signature(plugin_instance.display)
if"display_mode"insig.parameters:
returnplugin_instance.display(force_clear=True, display_mode=mode)

For a scroll plugin force_clear means "reset the scroll to the start", so even repeated calls through this path would never advance.

3. Frozen clock._freeze uses freezegun.freeze_time(freeze_time) with the default tick=False, so a scroll driven by elapsed wall time never moves.

Measurement

Driving display() properly — one force_clear=True frame, then force_clear=False frames, under freeze_time(..., tick=True) — at 128x64:

pluginwarnings from check_pluginreal?first frame with content
f1-scoreboard42 (7 modes × 6 sizes)noframes 2-4
ledmatrix-elections16 (2 modes × 8 sizes)noframe 4
ledmatrix-leaderboard2 (64x32, 64x64)noframe 38
nfl-draft8yesnever (300 frames)
starlark-apps8yesnever (300 frames)
on-air8deliberatenever (by design)

f1-scoreboard's own test/harness.json already documents the situation:

"the seven scroll modes (standings/results/qualifying/practice/sprint/calendar) start with a blank scroll-in buffer so a single-frame capture is empty and not worth committing"

— i.e. the plugin author knew, wrote it down, and the tool warns anyway on every run.

Suggested fix

Give the emptiness check a few frames before it concludes anything:

# in _render_size, after the first renderifresult.imageisnotNoneandnot_has_content(result.image):
for_inrange(EMPTY_RECHECK_FRAMES): # ~8 is enough; scrolls lit by frame 4 here_render_mode_no_clear(inst, mode)
if_has_content(dm.get_image()):
break

with two supporting changes:

  • a force_clear=False variant of _render_mode, so follow-up frames don't reset the scroll;
  • _freeze(..., tick=True) for the re-check (or advance the frozen clock explicitly between frames) so elapsed-time scrolls progress. Goldens should keep using the non-ticking freeze — only the emptiness re-check needs time to move.

Only warn if the mode is still blank after those frames. That keeps every true positive in the table above and drops all the noise.

Related, and worth considering separately: the core treats a None return as "don't skip" (display_controller.py:2110, if isinstance(result, bool)). The warning text says "so the mode is not skipped", which is accurate, but plugins annotated -> None are silently opted out of the skip contract. A stricter check — or a deprecation warning for display() implementations that never return a bool — would surface that class directly.

Environment

LEDMatrix v3.3.0-4-g0730d952, 256x64 rig, 44 installed plugins.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions