Solaar/lib
Ken Sanislo 9b627410b6 common: render RGB color values as 0xrrggbb in config and solaar show
24-bit RGB values stored in PerKeyLighting per-key maps and in
LEDEffectSetting `.color` fields currently dump as decimal integers in
both the YAML config file and `solaar show` output:

    per-key-lighting: {1: -1, 2: 16733440, 3: 16755200, ...}
    LEDs Keys: {1:-1, 2:16733440, 3:16755200, ...}

Hex is the canonical RGB representation. Render colors as `0xrrggbb`
everywhere: solaar show output, repr, and YAML config dumps. Both new
values and legacy values from pre-existing YAML configs migrate
transparently.

Implementation: a `ColorInt(int)` subclass in `common.py`.

  - `str(c)` / `repr(c)` → `'0xrrggbb'` for 0..0xFFFFFF; falls back to
    decimal for out-of-range values so sentinels like
    `COLORSPLUS["No change"] = -1` still display naturally.
  - Constructor accepts ints AND hex strings (`'0xrrggbb'` or
    `'#rrggbb'`) so pre-existing configs that wrote decimal continue
    to load.
  - YAML representer emits a hex int literal (`tag:yaml.org,2002:int`
    with style `'0xrrggbb'`). YAML 1.1 parses hex int literals back as
    plain ints with no custom loader registration — values round-trip
    cleanly without a custom YAML tag.

Wiring:

  - `Range` gains a `value_type=int` field; `MapRangeValidator.validate_read`
    wraps results through `rng.value_type(...)`. PerKeyLighting's
    `_COLOR_RANGE` sets `value_type=ColorInt`; other Range users keep
    the int default with no behavior change.
  - PerKeyLighting overrides `update()` and `update_key_value()` to wrap
    raw ints in `ColorInt` at write time. `type(v) is int` (exact
    match, not isinstance) deliberately excludes NamedInt sentinels and
    avoids re-wrapping existing ColorInts.
  - `LEDEffectSetting.__init__` wraps the `color` param in `ColorInt`
    with the same guard, so zone-effect color round-trips as hex
    through `yaml.dump(setting)` / `val_to_string`.
  - `MapRangeValidator.to_string` re-wraps raw ints loaded from YAML
    (which `yaml.safe_load` returns as plain Python ints regardless of
    the choice's `value_type`) through `rng.value_type` before
    formatting. Without this, `solaar show` would render legacy saved
    values as decimal even after the rest of the pipeline is hex-aware.

Coverage: 12 new unit tests across `test_common.py` and
`test_settings_validator.py`:

  - ColorInt str/repr, equality with plain int, hex-string constructor
    (0x / 0X / # prefixes), out-of-range fallback to decimal, YAML
    dump format, plain-int round-trip on load, dict-value formatting.
  - MapRangeValidator.to_string: plain-int re-wrap via value_type,
    pass-through for already-wrapped ColorInts, NamedInt sentinel
    preservation, and no behavior change for int-typed Ranges.

Existing test fixtures updated: _PERKEY_COLOR_RANGE now carries
value_type=ColorInt to match runtime _COLOR_RANGE.

702 tests pass; pre-commit clean.
2026-05-12 12:51:36 -04:00
..
hid_parser Fix duplicate class field typo in HID parser data 2026-05-05 14:43:03 -04:00
hidapi device: Treat empty hidraw read as device removal (EOF) (#3174) 2026-04-14 11:56:01 -04:00
keysyms keysymdef: Rename key symbols 2024-10-11 07:42:38 -04:00
logitech_receiver common: render RGB color values as 0xrrggbb in config and solaar show 2026-05-12 12:51:36 -04:00
solaar cli: enumerate LED effects under RGB_EFFECTS / COLOR_LED_EFFECTS in solaar show (#3213) 2026-05-12 09:54:30 -04:00