mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-18 04:49:13 +00:00
fix: resolve CodeRabbit review and Codacy findings on #534
CodeRabbit raised six; all six were real. The test double had drifted ahead of production. VisualTestDisplayManager accepted set_scrolling_state(frame_hold=...) while DisplayManager did not, so such a call passed every harness run and would raise TypeError on the panel -- the one failure a safety harness exists to prevent. frame_hold belongs to the change that adds it to DisplayManager (#523), so it moves there and the double matches main again. The harness swallowed exceptions from re-rendered frames. _settle_loop re-renders a mode that came back blank, to give a scroll time to draw; returning silently on a crash meant a mode that renders one good frame and then explodes was reported as passing. Recorded on result.error now, keeping the captured frame so the failure stays inspectable. starlark-apps display() returned True after _display_frame() failed, so the controller held a dead frame for the whole display_duration instead of rotating on. _display_frame now returns bool on all three paths. run_plugin_tests.py used env.setdefault for PYTHONPATH and LEDMATRIX_CORE, so an inherited value won and the subprocess imported a different core than the one under test -- ledmatrix-plugins#467 exactly. Prepends PROJECT_ROOT and sets LEDMATRIX_CORE unconditionally. The on-demand mailbox is polled after every frame, ~125x/second on a scrolling mode, and the read is deliberately uncached, so it was that many disk reads per second to find nothing. Floored at 250ms, which is imperceptible for a web-UI click. Consuming it also deleted whatever was present rather than what had just been processed, so a request posted while the previous one was in flight was thrown away and never ran; the delete is now keyed by request_id. That narrows the window rather than closing it -- a true atomic claim needs a primitive the cache layer does not offer, and the code says so rather than implying otherwise. Codacy's 2 criticals were bandit B404/B603 on the subprocess call added to run_plugin_tests.py. Fixed interpreter, argument list, no shell; annotated with the repo's existing nosec convention. Bandit is clean on the file. Adds test/test_on_demand_mailbox.py (8), test_starlark_display_contract.py (4) and two settle cases in test_harness_empty_claimed.py. 4, 4 and 2 of those fail against the pre-fix code. Full suite: 3961 passed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014RRtqXDCnvnY6EQwhT5CV9
This commit is contained in:
co-authored by
Claude Opus 5
parent
d9f6b110bc
commit
80781dda46
@@ -256,11 +256,14 @@ def _settle_loop(inst, mode, dm, result, freezer) -> None:
|
||||
time.sleep(EMPTY_RECHECK_STEP)
|
||||
try:
|
||||
result.display_returned = _render_mode_again(inst, mode)
|
||||
except Exception: # noqa: BLE001
|
||||
except Exception as e: # noqa: BLE001
|
||||
# Deliberately broad: this calls a plugin's display(), which can
|
||||
# raise anything. The first frame already rendered, so whatever
|
||||
# happens on a re-draw must not turn a good result into an error --
|
||||
# keep the frame we have and stop probing.
|
||||
# raise anything. Recorded rather than swallowed -- a mode that
|
||||
# renders one good frame and then crashes on the next is broken,
|
||||
# and returning silently here reported it as passing. The frame
|
||||
# already captured stays on the result so the failure is still
|
||||
# inspectable.
|
||||
result.error = repr(e)
|
||||
return
|
||||
image = dm.get_image()
|
||||
if _has_content(image):
|
||||
|
||||
@@ -506,16 +506,17 @@ class VisualTestDisplayManager:
|
||||
# Scrolling state (no-op interface compat)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def set_scrolling_state(self, is_scrolling: bool, frame_hold: int = 1):
|
||||
def set_scrolling_state(self, is_scrolling: bool):
|
||||
"""Set the current scrolling state (no-op for testing).
|
||||
|
||||
``frame_hold`` mirrors DisplayManager.set_scrolling_state so a plugin
|
||||
that paces its scroll can be rendered here. Without it every such
|
||||
plugin raised TypeError at render time and failed every size, which is
|
||||
invisible until a plugin happens to pass the argument.
|
||||
Deliberately mirrors DisplayManager.set_scrolling_state exactly. A
|
||||
double that accepts arguments production does not lets a call pass
|
||||
every harness run and then raise TypeError on the panel, which is the
|
||||
one failure a safety harness exists to prevent. ``frame_hold`` arrives
|
||||
here in the same change that adds it to DisplayManager (#523), not
|
||||
before.
|
||||
"""
|
||||
self._scrolling_state['is_scrolling'] = is_scrolling
|
||||
self._scrolling_state['frame_hold'] = frame_hold
|
||||
if is_scrolling:
|
||||
self._scrolling_state['last_scroll_activity'] = time.time()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user