mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-14 02:56:36 +00:00
refactor(sports): one reader for element colours and layout offsets
There were two copies of the per-element colour read and three of the layout-offset read. They had already drifted -- the scroll-card renderer carries a comment about having ignored offsets its own schema advertised -- and each new capability had to be added to all of them or silently work in some places and not others. All of them now go through src.element_style, which is what carries the alias handling and the per-mode lookup. That lands immediately for the nine plugins importing these modules: a scoreboard asking for `score_text` offsets finds the `layout.score` its users configured, and a Live instance resolves its own colours through SKIN_MODE without any call site passing a mode. _normalize_color learned "#RRGGBB" in the process. The scoreboards' own readers have always accepted it, so the shared one had to, or consolidating would have quietly dropped a form users' configs may hold. _coerce_offset picked up the non-finite guard the scroll-card reader had and the other two did not. _get_layout_offset is promoted onto SportsCoreSharedMixin. Each plugin still carries its own copy in its bundled sports.py, which wins by MRO -- so adopting this is a deletion in the plugin, and until that deletion nothing changes for it. Note for whoever runs the suite next: test_display_dirty_tracking.py is order-dependent. Fifteen of its tests failed in one full run and passed in the next with no change in between, and pass in isolation. Pre-existing, unrelated to this, but it makes a full-run diff untrustworthy until it is fixed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -422,3 +422,43 @@ class TestUnshareKeepsTheLayoutEngine:
|
||||
fonts = {"score": shared, "time": shared}
|
||||
self._host()._unshare_element_fonts(fonts)
|
||||
assert fonts["time"].getlength("88-88") == shared.getlength("88-88")
|
||||
|
||||
|
||||
class TestPromotedLayoutOffset:
|
||||
"""_get_layout_offset moved here so every scoreboard reads offsets the
|
||||
way the scroll card does.
|
||||
|
||||
Each plugin still carries its own copy in its bundled sports.py, which
|
||||
wins by MRO. That is the migration property: adopting this is a
|
||||
deletion in the plugin, and until that deletion nothing changes.
|
||||
"""
|
||||
|
||||
CONFIG = {"customization": {
|
||||
"layout": {"score": {"y_offset": -3}},
|
||||
"modes": {"recent": {"layout": {"score": {"y_offset": 9}}}},
|
||||
}}
|
||||
|
||||
def _host(self, **attrs):
|
||||
return type("H", (SportsCoreSharedMixin,),
|
||||
dict({"config": self.CONFIG}, **attrs))()
|
||||
|
||||
def test_it_reads_the_configured_offset(self):
|
||||
assert self._host()._get_layout_offset("score", "y_offset") == -3
|
||||
|
||||
def test_it_resolves_through_an_alias(self):
|
||||
"""What a plugin gains by deleting its own copy: the style block
|
||||
says score_text where the layout block says score."""
|
||||
assert self._host()._get_layout_offset("score_text", "y_offset") == -3
|
||||
|
||||
def test_skin_mode_selects_the_per_mode_offset(self):
|
||||
assert self._host(SKIN_MODE="recent")._get_layout_offset(
|
||||
"score", "y_offset") == 9
|
||||
|
||||
def test_a_plugins_own_copy_still_wins(self):
|
||||
"""Until a plugin deletes its copy, this changes nothing for it."""
|
||||
host = self._host(
|
||||
_get_layout_offset=lambda self, element, axis, default=0: 99)
|
||||
assert host._get_layout_offset("score", "y_offset") == 99
|
||||
|
||||
def test_an_unset_offset_is_the_default(self):
|
||||
assert self._host()._get_layout_offset("nothing", "y_offset", 5) == 5
|
||||
|
||||
Reference in New Issue
Block a user