Exemplo n.º 1
0
 def test_strip_modifiers(self):
     seq = keyutils.KeySequence(Qt.Key_0,
                                Qt.Key_1 | Qt.KeypadModifier,
                                Qt.Key_A | Qt.ControlModifier)
     expected = keyutils.KeySequence(Qt.Key_0,
                                     Qt.Key_1,
                                     Qt.Key_A | Qt.ControlModifier)
     assert seq.strip_modifiers() == expected
Exemplo n.º 2
0
 def clear_keystring(self) -> None:
     """Clear the currently entered key sequence."""
     if self._sequence:
         self._debug_log("Clearing keystring (was: {}).".format(
             self._sequence))
         self._sequence = keyutils.KeySequence()
         self._count = ''
         self.keystring_updated.emit('')
Exemplo n.º 3
0
 def __init__(self, win_id: int, parent: QWidget = None) -> None:
     super().__init__(parent)
     self._win_id = win_id
     self._modename = None
     self._sequence = keyutils.KeySequence()
     self._count = ''
     self.bindings = BindingTrie()
     config.instance.changed.connect(self._on_config_changed)
Exemplo n.º 4
0
 def __init__(self, win_id, parent=None, supports_count=True):
     super().__init__(parent)
     self._win_id = win_id
     self._modename = None
     self._sequence = keyutils.KeySequence()
     self._count = ''
     self._supports_count = supports_count
     self.bindings = {}
     config.instance.changed.connect(self._on_config_changed)
Exemplo n.º 5
0
 def test_iter(self):
     seq = keyutils.KeySequence(Qt.Key_A | Qt.ControlModifier,
                                Qt.Key_B | Qt.ShiftModifier,
                                Qt.Key_C,
                                Qt.Key_D,
                                Qt.Key_E)
     expected = [keyutils.KeyInfo(Qt.Key_A, Qt.ControlModifier),
                 keyutils.KeyInfo(Qt.Key_B, Qt.ShiftModifier),
                 keyutils.KeyInfo(Qt.Key_C, Qt.NoModifier),
                 keyutils.KeyInfo(Qt.Key_D, Qt.NoModifier),
                 keyutils.KeyInfo(Qt.Key_E, Qt.NoModifier)]
     assert list(seq) == expected
Exemplo n.º 6
0
 def __init__(self, *, mode: usertypes.KeyMode,
              win_id: int,
              parent: QObject = None,
              do_log: bool = True,
              passthrough: bool = False,
              supports_count: bool = True) -> None:
     super().__init__(parent)
     self._win_id = win_id
     self._sequence = keyutils.KeySequence()
     self._count = ''
     self._mode = mode
     self._do_log = do_log
     self.passthrough = passthrough
     self._supports_count = supports_count
     self.bindings = BindingTrie()
     self._read_config()
     config.instance.changed.connect(self._on_config_changed)
Exemplo n.º 7
0
 def test_bool(self):
     seq1 = keyutils.KeySequence.parse('abcd')
     seq2 = keyutils.KeySequence()
     assert seq1
     assert not seq2
Exemplo n.º 8
0
 def test_repr(self):
     seq = keyutils.KeySequence(Qt.Key_A | Qt.ControlModifier,
                                Qt.Key_B | Qt.ShiftModifier)
     assert repr(seq) == ("<qutebrowser.keyinput.keyutils.KeySequence "
                          "keys='<Ctrl+a>B'>")
Exemplo n.º 9
0
 def test_init_unknown(self, key):
     with pytest.raises(keyutils.KeyParseError):
         keyutils.KeySequence(key)
Exemplo n.º 10
0
 def test_init_empty(self):
     seq = keyutils.KeySequence()
     assert not seq
Exemplo n.º 11
0
 def test_init(self):
     seq = keyutils.KeySequence(Qt.Key_A, Qt.Key_B, Qt.Key_C, Qt.Key_D,
                                Qt.Key_E)
     assert len(seq._sequences) == 2
     assert len(seq._sequences[0]) == 4
     assert len(seq._sequences[1]) == 1
Exemplo n.º 12
0
 def test_fake_mac(self, fake_keyevent, modifiers, expected):
     """Make sure Control/Meta are swapped with a simulated Mac."""
     seq = keyutils.KeySequence()
     event = fake_keyevent(key=Qt.Key_A, modifiers=modifiers)
     new = seq.append_event(event)
     assert new[0] == keyutils.KeyInfo(Qt.Key_A, expected)
Exemplo n.º 13
0
def test_surrogate_sequences(keys, expected):
    seq = keyutils.KeySequence(*keys)
    assert str(seq) == expected
Exemplo n.º 14
0
 def _clear_partial_match(self) -> None:
     """Clear a partial keystring after a timeout."""
     self._debug_log("Clearing partial keystring {}".format(self._sequence))
     self._sequence = keyutils.KeySequence()
     self.keystring_updated.emit(str(self._sequence))
Exemplo n.º 15
0
 def test_append_event_invalid(self, key):
     seq = keyutils.KeySequence()
     event = QKeyEvent(QKeyEvent.KeyPress, key, Qt.NoModifier, '')
     with pytest.raises(keyutils.KeyParseError):
         seq.append_event(event)
Exemplo n.º 16
0
 def test_with_mappings(self):
     seq = keyutils.KeySequence.parse('foobar')
     mappings = {keyutils.KeySequence('b'): keyutils.KeySequence('t')}
     seq2 = seq.with_mappings(mappings)
     assert seq2 == keyutils.KeySequence.parse('footar')
Exemplo n.º 17
0
class TestKeySequence:

    def test_init(self):
        seq = keyutils.KeySequence(Qt.Key_A, Qt.Key_B, Qt.Key_C, Qt.Key_D,
                                   Qt.Key_E)
        assert len(seq._sequences) == 2
        assert len(seq._sequences[0]) == 4
        assert len(seq._sequences[1]) == 1

    def test_init_empty(self):
        seq = keyutils.KeySequence()
        assert not seq

    @pytest.mark.parametrize('key', [Qt.Key_unknown, -1, '\x1f', 0])
    def test_init_unknown(self, key):
        with pytest.raises(keyutils.KeyParseError):
            keyutils.KeySequence(key)

    @pytest.mark.parametrize('orig, normalized', [
        ('<Control+x>', '<Ctrl+x>'),
        ('<Windows+x>', '<Meta+x>'),
        ('<Mod1+x>', '<Alt+x>'),
        ('<Mod4+x>', '<Meta+x>'),
        ('<Control-->', '<Ctrl+->'),
        ('<Windows++>', '<Meta++>'),
        ('<ctrl-x>', '<Ctrl+x>'),
        ('<control+x>', '<Ctrl+x>'),
        ('<a>b', 'ab'),
    ])
    def test_str_normalization(self, orig, normalized):
        assert str(keyutils.KeySequence.parse(orig)) == normalized

    def test_iter(self):
        seq = keyutils.KeySequence(Qt.Key_A | Qt.ControlModifier,
                                   Qt.Key_B | Qt.ShiftModifier,
                                   Qt.Key_C,
                                   Qt.Key_D,
                                   Qt.Key_E)
        expected = [keyutils.KeyInfo(Qt.Key_A, Qt.ControlModifier),
                    keyutils.KeyInfo(Qt.Key_B, Qt.ShiftModifier),
                    keyutils.KeyInfo(Qt.Key_C, Qt.NoModifier),
                    keyutils.KeyInfo(Qt.Key_D, Qt.NoModifier),
                    keyutils.KeyInfo(Qt.Key_E, Qt.NoModifier)]
        assert list(seq) == expected

    def test_repr(self):
        seq = keyutils.KeySequence(Qt.Key_A | Qt.ControlModifier,
                                   Qt.Key_B | Qt.ShiftModifier)
        assert repr(seq) == ("<qutebrowser.keyinput.keyutils.KeySequence "
                             "keys='<Ctrl+a>B'>")

    @pytest.mark.parametrize('sequences, expected', [
        (['a', ''], ['', 'a']),
        (['abcdf', 'abcd', 'abcde'], ['abcd', 'abcde', 'abcdf']),
    ])
    def test_sorting(self, sequences, expected):
        result = sorted(keyutils.KeySequence.parse(seq) for seq in sequences)
        expected_result = [keyutils.KeySequence.parse(seq) for seq in expected]
        assert result == expected_result

    @pytest.mark.parametrize('seq1, seq2, op, result', [
        ('a', 'a', operator.eq, True),
        ('a', '<a>', operator.eq, True),
        ('a', '<Shift-a>', operator.eq, False),
        ('a', 'b', operator.lt, True),
        ('a', 'b', operator.le, True),
    ])
    def test_operators(self, seq1, seq2, op, result):
        seq1 = keyutils.KeySequence.parse(seq1)
        seq2 = keyutils.KeySequence.parse(seq2)
        assert op(seq1, seq2) == result

        opposite = {
            operator.lt: operator.ge,
            operator.gt: operator.le,
            operator.le: operator.gt,
            operator.ge: operator.lt,
            operator.eq: operator.ne,
            operator.ne: operator.eq,
        }
        assert opposite[op](seq1, seq2) != result

    @pytest.mark.parametrize('seq1, seq2, equal', [
        ('a', 'a', True),
        ('a', 'A', False),
        ('a', '<a>', True),
        ('abcd', 'abcde', False),
    ])
    def test_hash(self, seq1, seq2, equal):
        seq1 = keyutils.KeySequence.parse(seq1)
        seq2 = keyutils.KeySequence.parse(seq2)
        assert (hash(seq1) == hash(seq2)) == equal

    @pytest.mark.parametrize('seq, length', [
        ('', 0),
        ('a', 1),
        ('A', 1),
        ('<Ctrl-a>', 1),
        ('abcde', 5)
    ])
    def test_len(self, seq, length):
        assert len(keyutils.KeySequence.parse(seq)) == length

    def test_bool(self):
        seq1 = keyutils.KeySequence.parse('abcd')
        seq2 = keyutils.KeySequence()
        assert seq1
        assert not seq2

    def test_getitem(self):
        seq = keyutils.KeySequence.parse('ab')
        expected = keyutils.KeyInfo(Qt.Key_B, Qt.NoModifier)
        assert seq[1] == expected

    def test_getitem_slice(self):
        s1 = 'abcdef'
        s2 = 'de'
        seq = keyutils.KeySequence.parse(s1)
        expected = keyutils.KeySequence.parse(s2)
        assert s1[3:5] == s2
        assert seq[3:5] == expected

    @pytest.mark.parametrize('entered, configured, expected', [
        # config: abcd
        ('abc', 'abcd', QKeySequence.PartialMatch),
        ('abcd', 'abcd', QKeySequence.ExactMatch),
        ('ax', 'abcd', QKeySequence.NoMatch),
        ('abcdef', 'abcd', QKeySequence.NoMatch),

        # config: abcd ef
        ('abc', 'abcdef', QKeySequence.PartialMatch),
        ('abcde', 'abcdef', QKeySequence.PartialMatch),
        ('abcd', 'abcdef', QKeySequence.PartialMatch),
        ('abcdx', 'abcdef', QKeySequence.NoMatch),
        ('ax', 'abcdef', QKeySequence.NoMatch),
        ('abcdefg', 'abcdef', QKeySequence.NoMatch),
        ('abcdef', 'abcdef', QKeySequence.ExactMatch),

        # other examples
        ('ab', 'a', QKeySequence.NoMatch),

        # empty strings
        ('', '', QKeySequence.ExactMatch),
        ('', 'a', QKeySequence.PartialMatch),
        ('a', '', QKeySequence.NoMatch),
    ])
    def test_matches(self, entered, configured, expected):
        entered = keyutils.KeySequence.parse(entered)
        configured = keyutils.KeySequence.parse(configured)
        assert entered.matches(configured) == expected

    @pytest.mark.parametrize('old, key, modifiers, text, expected', [
        ('a', Qt.Key_B, Qt.NoModifier, 'b', 'ab'),
        ('a', Qt.Key_B, Qt.ShiftModifier, 'B', 'aB'),
        ('a', Qt.Key_B, Qt.ControlModifier | Qt.ShiftModifier, 'B',
         'a<Ctrl+Shift+b>'),

        # Modifier stripping with symbols
        ('', Qt.Key_Colon, Qt.NoModifier, ':', ':'),
        ('', Qt.Key_Colon, Qt.ShiftModifier, ':', ':'),
        ('', Qt.Key_Colon, Qt.ControlModifier | Qt.ShiftModifier, ':',
         '<Ctrl+Shift+:>'),

        # Handling of Backtab
        ('', Qt.Key_Backtab, Qt.NoModifier, '', '<Backtab>'),
        ('', Qt.Key_Backtab, Qt.ShiftModifier, '', '<Shift+Tab>'),
        ('', Qt.Key_Backtab, Qt.ControlModifier | Qt.ShiftModifier, '',
         '<Control+Shift+Tab>'),

        # Stripping of Qt.GroupSwitchModifier
        ('', Qt.Key_A, Qt.GroupSwitchModifier, 'a', 'a'),
    ])
    def test_append_event(self, old, key, modifiers, text, expected):
        seq = keyutils.KeySequence.parse(old)
        event = QKeyEvent(QKeyEvent.KeyPress, key, modifiers, text)
        new = seq.append_event(event)
        assert new == keyutils.KeySequence.parse(expected)

    @pytest.mark.parametrize('key', [Qt.Key_unknown, 0x0])
    def test_append_event_invalid(self, key):
        seq = keyutils.KeySequence()
        event = QKeyEvent(QKeyEvent.KeyPress, key, Qt.NoModifier, '')
        with pytest.raises(keyutils.KeyParseError):
            seq.append_event(event)

    def test_with_mappings(self):
        seq = keyutils.KeySequence.parse('foobar')
        mappings = {keyutils.KeySequence('b'): keyutils.KeySequence('t')}
        seq2 = seq.with_mappings(mappings)
        assert seq2 == keyutils.KeySequence.parse('footar')

    @pytest.mark.parametrize('keystr, expected', [
        ('<Ctrl-Alt-y>',
         keyutils.KeySequence(Qt.ControlModifier | Qt.AltModifier | Qt.Key_Y)),
        ('x', keyutils.KeySequence(Qt.Key_X)),
        ('X', keyutils.KeySequence(Qt.ShiftModifier | Qt.Key_X)),
        ('<Escape>', keyutils.KeySequence(Qt.Key_Escape)),
        ('xyz', keyutils.KeySequence(Qt.Key_X, Qt.Key_Y, Qt.Key_Z)),
        ('<Control-x><Meta-y>',
         keyutils.KeySequence(Qt.ControlModifier | Qt.Key_X,
                              Qt.MetaModifier | Qt.Key_Y)),

        ('<Shift-x>', keyutils.KeySequence(Qt.ShiftModifier | Qt.Key_X)),
        ('<Alt-x>', keyutils.KeySequence(Qt.AltModifier | Qt.Key_X)),
        ('<Control-x>', keyutils.KeySequence(Qt.ControlModifier | Qt.Key_X)),
        ('<Meta-x>', keyutils.KeySequence(Qt.MetaModifier | Qt.Key_X)),
        ('<Num-x>', keyutils.KeySequence(Qt.KeypadModifier | Qt.Key_X)),

        ('>', keyutils.KeySequence(Qt.Key_Greater)),
        ('<', keyutils.KeySequence(Qt.Key_Less)),
        ('a>', keyutils.KeySequence(Qt.Key_A, Qt.Key_Greater)),
        ('a<', keyutils.KeySequence(Qt.Key_A, Qt.Key_Less)),
        ('>a', keyutils.KeySequence(Qt.Key_Greater, Qt.Key_A)),
        ('<a', keyutils.KeySequence(Qt.Key_Less, Qt.Key_A)),
        ('<alt+greater>',
         keyutils.KeySequence(Qt.Key_Greater | Qt.AltModifier)),
        ('<alt+less>',
         keyutils.KeySequence(Qt.Key_Less | Qt.AltModifier)),

        ('<alt+<>', keyutils.KeyParseError),
        ('<alt+>>', keyutils.KeyParseError),
        ('<blub>', keyutils.KeyParseError),
        ('<>', keyutils.KeyParseError),
        ('\U00010000', keyutils.KeyParseError),
    ])
    def test_parse(self, keystr, expected):
        if expected is keyutils.KeyParseError:
            with pytest.raises(keyutils.KeyParseError):
                keyutils.KeySequence.parse(keystr)
        else:
            assert keyutils.KeySequence.parse(keystr) == expected

    @hypothesis.given(strategies.text())
    def test_parse_hypothesis(self, keystr):
        try:
            seq = keyutils.KeySequence.parse(keystr)
        except keyutils.KeyParseError:
            pass
        else:
            str(seq)