diff --git a/qutebrowser/keyinput/keyutils.py b/qutebrowser/keyinput/keyutils.py index d89f9aa5c..fd00cf5b5 100644 --- a/qutebrowser/keyinput/keyutils.py +++ b/qutebrowser/keyinput/keyutils.py @@ -38,7 +38,18 @@ _MODIFIER_MAP = { } +def _assert_plain_key(key): + """Make sure this is a key without KeyboardModifiers mixed in.""" + assert not key & Qt.KeyboardModifierMask, hex(key) + + +def _assert_plain_modifier(key): + """Make sure this is a modifier without a key mixed in.""" + assert not key & ~Qt.KeyboardModifierMask, hex(key) + + def is_printable(key): + _assert_plain_key(key) return key <= 0xff and key not in [Qt.Key_Space, 0x0] @@ -48,6 +59,7 @@ def is_modifier_key(key): This only considers keys which are part of Qt::KeyboardModifiers, i.e. which would interrupt a key chain like "yY" when handled. """ + _assert_plain_key(key) return key in _MODIFIER_MAP @@ -73,6 +85,7 @@ def _key_to_string(key): Return: A name of the key as a string. """ + _assert_plain_key(key) special_names_str = { # Some keys handled in a weird way by QKeySequence::toString. # See https://bugreports.qt.io/browse/QTBUG-40030 @@ -155,6 +168,7 @@ def _modifiers_to_string(modifiers): Handles Qt.GroupSwitchModifier because Qt doesn't handle that as a modifier. """ + _assert_plain_modifier(modifiers) if modifiers & Qt.GroupSwitchModifier: modifiers &= ~Qt.GroupSwitchModifier result = 'AltGr+' @@ -446,6 +460,9 @@ class KeySequence: key = ev.key() modifiers = ev.modifiers() + _assert_plain_key(key) + _assert_plain_modifier(modifiers) + if key == 0x0: raise KeyParseError(None, "Got nil key!") diff --git a/tests/unit/keyinput/test_keyutils.py b/tests/unit/keyinput/test_keyutils.py index 097b72b71..0ec8814f1 100644 --- a/tests/unit/keyinput/test_keyutils.py +++ b/tests/unit/keyinput/test_keyutils.py @@ -444,7 +444,6 @@ def test_key_info_to_event(): (Qt.Key_Return, False), (Qt.Key_Enter, False), (Qt.Key_Space, False), - (Qt.Key_X | Qt.ControlModifier, False), # Wrong usage (0x0, False), # Used by Qt for unknown keys (Qt.Key_ydiaeresis, True), @@ -461,3 +460,16 @@ def test_is_printable(key, printable): ]) def test_is_modifier_key(key, ismodifier): assert keyutils.is_modifier_key(key) == ismodifier + + +@pytest.mark.parametrize('code', [ + lambda a: keyutils._assert_plain_key(a), + lambda a: keyutils._assert_plain_modifier(a), + lambda a: keyutils.is_printable(a), + lambda a: keyutils.is_modifier_key(a), + lambda a: keyutils._key_to_string(a), + lambda a: keyutils._modifiers_to_string(a), +]) +def test_non_plain(code): + with pytest.raises(AssertionError): + code(Qt.Key_X | Qt.ControlModifier)