device: Handle composite IntFlag.name on Python < 3.11 (#3187)
* Handle composite IntFlag.name on Python < 3.11 On Python < 3.11, IntFlag.name returns None for composite flags (e.g. NotificationFlag(0x000900) = SOFTWARE_PRESENT|WIRELESS). The previous fix (#3184) returns an empty list in this case, losing the flag names. This commit decomposes composite flags manually by iterating over enum members, producing correct results on all supported Python versions (>= 3.8 as declared in setup.py). Add regression tests covering composite flags and None input. Tested on: - Python 3.9.2 (Debian 11): 56/56 passed - Python 3.11.15 (pyenv): 56/56 passed Refs #3184 * Fix line length style violation (E501) Move comment above the parametrize entry to stay under 127 chars. --------- Co-authored-by: avercelli <avercelli@vulog.com>
This commit is contained in:
parent
0a6421ef82
commit
8b023115d2
|
|
@ -91,9 +91,12 @@ class NotificationFlag(IntFlag):
|
|||
@classmethod
|
||||
def flag_names(cls, flags) -> List[str]:
|
||||
"""Extract the names of the flags from the integer."""
|
||||
if flags is None or flags.name is None:
|
||||
if flags is None:
|
||||
return []
|
||||
return flags.name.replace("_", " ").lower().split("|")
|
||||
if flags.name is not None:
|
||||
return flags.name.replace("_", " ").lower().split("|")
|
||||
# Python < 3.11: .name is None for composite flags, decompose manually
|
||||
return [m.name.replace("_", " ").lower() for m in cls if m.value and m in flags]
|
||||
|
||||
NUMPAD_NUMERICAL_KEYS = 0x800000
|
||||
F_LOCK_STATUS = 0x400000
|
||||
|
|
|
|||
|
|
@ -296,6 +296,32 @@ def test_notification_flag_str(flag_bits, expected_names):
|
|||
assert flag_names == expected_names
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"flags, expected",
|
||||
[
|
||||
(None, []),
|
||||
# composite flag, .name is None on Python < 3.11
|
||||
(hidpp10_constants.NotificationFlag(0x000900), ["software present", "wireless"]),
|
||||
(hidpp10_constants.NotificationFlag(0x100000), ["battery status"]),
|
||||
(hidpp10_constants.NotificationFlag(0x080000), ["mouse extra buttons"]),
|
||||
],
|
||||
)
|
||||
def test_notification_flag_names(flags, expected):
|
||||
result = hidpp10_constants.NotificationFlag.flag_names(flags)
|
||||
assert result == expected
|
||||
|
||||
|
||||
def test_notification_flag_names_none_does_not_crash():
|
||||
"""Regression test for #3184: flag_names crashes with AttributeError when
|
||||
flags.name is None, which happens with certain receiver firmware versions
|
||||
(e.g. Nano C52F reporting 0x000900)."""
|
||||
flags_with_none_name = hidpp10_constants.NotificationFlag(0x000900)
|
||||
result = hidpp10_constants.NotificationFlag.flag_names(flags_with_none_name)
|
||||
assert "software present" in result
|
||||
assert "wireless" in result
|
||||
assert isinstance(result, list)
|
||||
|
||||
|
||||
def test_get_device_features():
|
||||
result = _hidpp10.get_device_features(device_standard)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue