From f996808760f9bb869c60b7b8810725ff49b9b394 Mon Sep 17 00:00:00 2001 From: Peter Hutterer <peter.hutterer@who-t.net> Date: Mon, 12 Aug 2019 13:22:18 +1000 Subject: [PATCH] Prefix undefined event codes with an underscore Previously, event codes without a kernel define would resolve into properly named objects, e.g. libevdev.EV_REL.REL_0B This breaks the API whenever the kernel introduces a new define because that named object will just disappear. e.g. the above REL_0B is now REL_WHEEL_HI_RES. Since the undefined names aren't supposed to be used by callers directly anyway, rename them to be underscored instead: libevdev.EV_REL._REL_0B This means we can still return them from evbit() and events() but the underscore signals a private API. The actual name remains the same, so print(_REL_0B.name) will not have an underscore. This is to avoid bugs/breakage where the caller uses the 3-lettter prefix for other purposes. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> --- libevdev/const.py | 24 +++++++++++++++++++----- test/test_const.py | 4 ++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/libevdev/const.py b/libevdev/const.py index eeb19ee..b68c517 100644 --- a/libevdev/const.py +++ b/libevdev/const.py @@ -91,7 +91,17 @@ class EventCode(EvdevBit): .. attribute:: name - The string name of this event code + The string name of this event code. Where the name is not defined, a + fake name is generated by this module, consisting of the prefix and + the uppercase hexadecimal value, e.g. ``REL_0B``. These generated + names (see :func:`EventCode.is_defined()`) should never be used as + input. + + Note that even defined names are not a stable API. From time to time + the kernel introduces a new name and aliases the old one. The same + numeric event code may then return a different name than before. + This does not affect the :func:`evbit()` function which continues to + return the correct event code. .. attribute:: type @@ -356,15 +366,19 @@ def _load_consts(): codes = [] for c in range(cmax + 1): cname = Libevdev.event_to_name(t, c) + name = cname has_name = cname is not None - # For those without names, we just use the type name plus - # hexcode + # For those without names, we use the type name plus + # hexcode for the actual name, but a prefixing underscore for + # the class name (it's not stable API). + # i.e. libedev.EV_REL._REL_0B.name == 'REL_0B' if cname is None: - cname = "{}_{:02X}".format(tname[3:], c) + name = "{}_{:02X}".format(tname[3:], c) + cname = "_{}".format(name) new_class = type(cname, (EventCode, ), {'type': type_object, - 'name': cname, + 'name': name, 'value': c, 'is_defined': has_name}) code_object = new_class() diff --git a/test/test_const.py b/test/test_const.py index 6563d56..3c9ce28 100644 --- a/test/test_const.py +++ b/test/test_const.py @@ -97,6 +97,10 @@ class TestEventBits(unittest.TestCase): else: self.assertEqual(c.name, fake_name) + def test_evcode_undefined(self): + self.assertEqual(evbit('SYN_04'), libevdev.EV_SYN._SYN_04) + self.assertEqual(libevdev.EV_SYN._SYN_04.name, 'SYN_04') + def test_propbit_string(self): self.assertEqual(propbit('INPUT_PROP_POINTER'), libevdev.INPUT_PROP_POINTER) self.assertEqual(propbit('INPUT_PROP_DIRECT'), libevdev.INPUT_PROP_DIRECT) -- GitLab