From ed5b5e6d07a4c82ec73c0ece60e731b86bc011dd Mon Sep 17 00:00:00 2001 From: ChuckBuilds Date: Wed, 2 Sep 2026 18:44:19 -0400 Subject: [PATCH] release: report 3.3.0, so the version the gate reads matches the tag v3.3.0 is tagged, but src/__init__.py still says "3.2.0" -- and that string, not the git tag, is what the compatibility gate compares (store_manager.py: `from src import __version__ as core_version`). The effect is that every plugin flooring at 3.3.0 is refused on a device running 3.3.0. Checked against the real gate and the real manifest: core __version__ reported to the gate : 3.2.0 hockey floor : 3.3.0 verdict : REFUSE "supports LEDMatrix >=3.3.0, but this system is running 3.2.0" That is all eight sports scoreboards plus calendar 1.2.3, and it would read as a broken plugin store rather than a stale constant. The TRUSTWORTHY_FLOOR escape hatch does not cover this: it exempts cores reporting below 2.0.0 as "unknown rather than old", and 3.2.0 is above it, so the number is trusted and compared. This is the same slip as v3.1.0, which was tagged six weeks before its version string was bumped and shipped __version__ = "1.0.0" -- the reason that escape hatch exists at all. With the bump, the same gate call returns ALLOW for hockey at both the sports_card and sports_shared floors, and for calendar 1.2.3. CHANGELOG.md gains the 3.3.0 section. That file is what plugin authors read to decide which release to floor on, so it records the three new modules -- src/common/sports_card.py, sports_game_renderer.py and sports_shared.py -- against this version, along with the three traps in adopting the mixins. No test pinned the old literal; the ones that care monkeypatch __version__. 135 compatibility tests pass. --- CHANGELOG.md | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ src/__init__.py | 2 +- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db5ea778..ab90b8e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,81 @@ release that ships it. accepts both, but the store flags the old spelling as deprecated (`store_manager.py`) and only the new one is in `schema/manifest_schema.json`. +## 3.3.0 + +**The release the sports scoreboards floor on to delete their bundled copies.** +3.2.0 shipped the unified sports library and made `ledmatrix_min_version` +enforceable; this ships the last three shared modules and completes the store +gate, so a scoreboard can now floor here and carry no fallback at all. + +New modules a plugin may import via `src.*` and floor on 3.3.0 for: + +- `src/common/sports_card.py` — settings, colour, font and date helpers for a + scoreboard's `game_renderer.py`. Free functions taking `config`/`fonts` + explicitly, so nothing about the caller's class is assumed. +- `src/common/sports_game_renderer.py` — `SportsGameRendererMixin`: scroll/Vegas + card geometry (centre gap, logo slot and cache key, layout offsets, the + upcoming-card date and time layout). No `__init__` and no state, so adoption + is one line on the class statement. +- `src/common/sports_shared.py` — `SportsCoreSharedMixin`, + `SportsLiveSharedMixin`, `SportsRecentSharedMixin`: the `sports.py` bodies + byte-identical in all eight lineage-sharing scoreboards. + +All three sit under `src/common/` rather than `src/base_classes/sports/`, +deliberately: importing that package pulls `core.py` → `DisplayManager` → +`rgbmatrix`, and these are pure logic. Plugins importing them must not acquire a +hardware dependency. + +Three notes for anyone adopting `sports_shared`: + +- `SportsRecentSharedMixin` defines `__init__`. Its bare `super()` binds to the + mixin, so it reaches the host only when the mixin is listed **first** in the + bases. Reversing that order silently skips the host constructor. +- Methods that resolve the plugin's `config_schema.json` use `_plugin_dir()`, + which walks the MRO rather than reading `__file__` — `__file__` is now + `src/common/`. It walks because `SportsCore` is an ABC: a subclass built with + `type(name, bases, ns)` reports `__module__` as `"abc"`. +- `_get_timezone`, `_extract_game_details` and `_fetch_data` are byte-identical + across the eight but stay in the plugins. The first binds a per-plugin + timezone module whose contents differ; the other two are the abstract stubs + that define the sport. + +**The store's compatibility gate is now on every registry-managed route.** 3.2.0 +gated `install_plugin`. This release gates the git-pull update path and +`install_from_url`, so a plugin whose floor the core cannot meet is refused +after download with no partial directory left behind. + +### Fixed + +- **ESPN 403s.** `site.api` began rejecting the User-Agent strings this repo + sent on 2026-08-04; every shared-data-source scoreboard returned + `403 Forbidden`. Requests now send an identifying token with a project URL — + browser-style strings and bare custom tokens are both refused. +- **Low-memory boards becoming unreachable under load** while still answering + pings and serving the web UI. Fetched payloads are released after delivery + rather than pinned on the completed request for up to an hour, malloc arenas + are capped, and log volume and SD writes are reduced. Available memory is now + reported in Tools diagnostics. +- **A failed logo download pinning a team to a grey box**: the placeholder was + written under the real logo's filename, so later attempts found a file and + reported success without retrying. +- **A plugin enabled but never loaded is retried** rather than staying absent + with `error = null`. +- `ttl` now controls cache expiry; abandoned cache writes no longer leave temp + files; one cache-cleanup thread per directory rather than per manager. +- Odds are fetched for the games displayed, not the whole schedule window, and a + stalled ESPN no longer stalls the whole plugin update. +- Array-item secrets are no longer wiped or logged. +- A restored backup matches the device it was taken from. +- The web UI reports the real error instead of "unknown", rejects non-finite + JSON numbers, and stops checkbox groups posting back hidden options. + +### Added + +- `display.hardware.orientation` for panels mounted upside down. +- Vegas keeps live content in the ticker rather than being preempted by it. +- Schemas can label enum dropdown options. + ## 3.2.0 **The first release shipping the unified sports library.** This is the version diff --git a/src/__init__.py b/src/__init__.py index f8fa0daa..c73f8102 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -4,5 +4,5 @@ Core source package for the LED Matrix Display project. """ -__version__ = "3.2.0" +__version__ = "3.3.0"