diff --git a/src/common/sports_card.py b/src/common/sports_card.py index 5a1f8ebb..6b8bd7ea 100644 --- a/src/common/sports_card.py +++ b/src/common/sports_card.py @@ -17,10 +17,13 @@ the extra guard only stops a None size raising TypeError. """ +import logging from datetime import datetime, timezone from typing import Any, Dict, Optional, Tuple from zoneinfo import ZoneInfo +logger = logging.getLogger(__name__) + __all__ = [ "ELEMENT_FOR_FONT", "FAVORITE_RESULT_COLOR_DEFAULTS", "FONT_NAME_ALIASES", "FONT_PIXEL_GRID", "MONTH_ABBR", "WEEKDAY_ABBR", @@ -395,7 +398,14 @@ def schema_font_size(schema_path: str, element_key) -> Optional[int]: size = spec.get('properties', {}).get('font_size', {}).get('default') if size is not None: cache[key] = int(size) - except Exception: + except Exception as exc: + # See sports_shared._schema_font_size: an unreadable schema + # silently disables the pixel-grid snap for every element. + # Built once per schema path, so this cannot repeat per frame. + logger.warning( + "could not read %s (%s: %s); font sizes will skip their " + "pixel grid snap and may render a pixel narrow", + schema_path, type(exc).__name__, exc) cache = {} _SCHEMA_FONT_SIZE_CACHE[schema_path] = cache return cache.get(element_key) diff --git a/src/common/sports_shared.py b/src/common/sports_shared.py index 1187b846..b120e532 100644 --- a/src/common/sports_shared.py +++ b/src/common/sports_shared.py @@ -288,7 +288,23 @@ def _schema_font_size(self, element_key): size = spec.get('properties', {}).get('font_size', {}).get('default') if size is not None: cache[key] = int(size) - except Exception: + except Exception as exc: + # Say so. An unreadable schema is not cosmetic: every element's + # configured size then stops matching "the schema default", is + # treated as a deliberate user choice, and skips the snap to the + # font's pixel grid -- which renders 4x6-font.ttf at 6 instead + # of 7, a 3px-wide glyph instead of 4px. That shipped once, + # silently, and was found by a user counting pixels on a photo + # of the panel. + # + # Logged, not raised: a missing schema must not stop a plugin + # rendering. The cache is built once per class, so this cannot + # repeat per frame. + logger.warning( + "%s: could not read config_schema.json (%s: %s); every font " + "size will be treated as user-chosen and will skip its pixel " + "grid snap. Font sizes may render a pixel narrow.", + type(self).__name__, type(exc).__name__, exc) cache = {} self.__class__._SCHEMA_FONT_SIZES = cache return cache.get(element_key)