Esempio n. 1
0
class TestKeyMap_with_keychains(unittest.TestCase):
    def setUp(self):
        self.km = KeyMap(callback=self.handle_action)
        self.widget = self.km.wrap(urwid.Edit)('', 'Original Text')
        self.km.on_keychain(self.handle_keychain_changed)
        self._action_counter = 0

    def handle_action(self, action, widget):
        self._action_counter += 1
        widget.set_edit_text('%s%d' % (str(action), self._action_counter))

    def handle_keychain_changed(self, keymap, context, active_keychains, keys_given):
        self.active_keychains = set(active_keychains)

    def assert_status(self, active_keychains=(), keys_given=(), widget_text=None):
        self.assertEqual(self.active_keychains, set(active_keychains))
        self.assertEqual(self.km.current_keychain, tuple(keys_given))
        self.assertEqual(self.widget.text, widget_text)


    def test_any_keychain_started(self):
        def cb(*args, **kwargs): pass
        self.km.bind(key='a+b+c', action='foo')
        self.assertFalse(self.km.any_keychain_started)
        self.km.evaluate('a', callback=cb)
        self.assertTrue(self.km.any_keychain_started)
        self.km.evaluate('b', callback=cb)
        self.assertTrue(self.km.any_keychain_started)
        self.km.evaluate('c', callback=cb)
        self.assertFalse(self.km.any_keychain_started)

    def test_unbind(self):
        kc = '1 2 3'
        for keys in ('1', '1 2', '1 2 3'):
            self.km.bind(kc, 'foo')
            self.assertIn(KeyChain('1', '2', '3'), self.km.keys())
            self.km.unbind(keys)
            self.assertNotIn(KeyChain('1', '2', '3'), self.km.keys())

        for keys in ('1 3', '1 2 4', '1 2 3 4', '2', '3', '2 1', '3 2 1'):
            self.km.bind(kc, 'foo')
            self.assertIn(KeyChain('1', '2', '3'), self.km.keys())
            with self.assertRaises(ValueError) as cm:
                self.km.unbind(keys)
            self.assertIn('Key not mapped in context', str(cm.exception))
            self.assertIn(str(self.km.mkkey(keys)), str(cm.exception))

    def test_complete_chain(self):
        self.km.bind('alt-1 alt-2 alt-3', 'foo')

        self.widget.keypress((80,), 'alt-1')
        self.assert_status(keys_given=('alt-1',),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-2', 'alt-3'), 'foo'),))

        self.widget.keypress((80,), 'alt-2')
        self.assert_status(keys_given=('alt-1', 'alt-2'),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-2', 'alt-3'), 'foo'),))

        self.widget.keypress((80,), 'alt-3')
        self.assert_status(keys_given=(),
                           widget_text='foo1',
                           active_keychains=())

    def test_reverse_chain_with_backspace(self):
        self.km.bind('alt-1 alt-f alt-x', 'foo')
        self.km.bind('alt-1 alt-b alt-x', 'bar')

        self.widget.keypress((80,), 'alt-1')
        self.assert_status(keys_given=('alt-1',),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-f', 'alt-x'), 'foo'),
                                             (('alt-1', 'alt-b', 'alt-x'), 'bar')))

        self.widget.keypress((80,), 'alt-f')
        self.assert_status(keys_given=('alt-1', 'alt-f'),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-f', 'alt-x'), 'foo'),))

        self.widget.keypress((80,), 'backspace')
        self.assert_status(keys_given=('alt-1',),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-f', 'alt-x'), 'foo'),
                                             (('alt-1', 'alt-b', 'alt-x'), 'bar')))

        self.widget.keypress((80,), 'alt-b')
        self.assert_status(keys_given=('alt-1', 'alt-b'),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-b', 'alt-x'), 'bar'),))

        self.widget.keypress((80,), 'alt-x')
        self.assert_status(keys_given=(),
                           widget_text='bar1',
                           active_keychains=())

    def test_binding_backspace(self):
        self.km.bind('alt-1 backspace', 'foo')

        self.widget.keypress((80,), 'alt-1')
        self.assert_status(keys_given=('alt-1',),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'backspace'), 'foo'),))

        self.widget.keypress((80,), 'backspace')
        self.assert_status(keys_given=(),
                           widget_text='foo1',
                           active_keychains=())

    def test_abort_chain_with_unmapped_key(self):
        self.km.bind('alt-1 alt-2 alt-3', 'foo')

        self.widget.keypress((80,), 'alt-1')
        self.assert_status(keys_given=('alt-1',),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-2', 'alt-3'), 'foo'),))

        self.widget.keypress((80,), 'alt-x')
        self.assert_status(keys_given=(),
                           widget_text='Original Text',
                           active_keychains=())

    def test_abort_chain_with_mapped_key(self):
        self.km.bind('alt-1 alt-2 alt-3', 'foo')
        self.km.bind('alt-x', 'bar')

        self.widget.keypress((80,), 'alt-1')
        self.assert_status(keys_given=('alt-1',),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-2', 'alt-3'), 'foo'),))

        # Abort the started chain
        self.widget.keypress((80,), 'alt-x')
        self.assert_status(keys_given=(),
                           widget_text='Original Text',
                           active_keychains=())

        # Mapped single-key evaluation works again
        self.widget.keypress((80,), 'alt-x')
        self.assert_status(keys_given=(),
                           widget_text='bar1',
                           active_keychains=())

    def test_abort_chain_with_builtin_key(self):
        self.km.bind('alt-1 alt-2 alt-3', 'foo')

        self.widget.keypress((80,), 'alt-1')
        self.assert_status(keys_given=('alt-1',),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-2', 'alt-3'), 'foo'),))

        # This would usually append 'x' to the Edit widget text, but we want it
        # to abort the started chain instead.
        self.widget.keypress((80,), 'x')
        self.assert_status(keys_given=(),
                           widget_text='Original Text',
                           active_keychains=())

        # Now we can change the text again
        self.widget.keypress((80,), 'x')
        self.assert_status(keys_given=(),
                           widget_text='Original Textx',
                           active_keychains=())

    def test_competing_chains(self):
        self.km.bind('alt-1 alt-2 alt-a', 'foo')
        self.km.bind('alt-1 alt-2 alt-b', 'bar')

        self.widget.keypress((80,), 'alt-1')
        self.assert_status(keys_given=('alt-1',),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-2', 'alt-a'), 'foo'),
                                             (('alt-1', 'alt-2', 'alt-b'), 'bar')))

        self.widget.keypress((80,), 'alt-2')
        self.assert_status(keys_given=('alt-1', 'alt-2'),
                           widget_text='Original Text',
                           active_keychains=((('alt-1', 'alt-2', 'alt-a'), 'foo'),
                                             (('alt-1', 'alt-2', 'alt-b'), 'bar')))

        self.widget.keypress((80,), 'alt-a')
        self.assert_status(keys_given=(),
                           widget_text='foo1',
                           active_keychains=())

        self.widget.keypress((80,), 'alt-1')
        self.assert_status(keys_given=('alt-1',),
                           widget_text='foo1',
                           active_keychains=((('alt-1', 'alt-2', 'alt-a'), 'foo'),
                                             (('alt-1', 'alt-2', 'alt-b'), 'bar')))

        self.widget.keypress((80,), 'alt-2')
        self.assert_status(keys_given=('alt-1', 'alt-2'),
                           widget_text='foo1',
                           active_keychains=((('alt-1', 'alt-2', 'alt-a'), 'foo'),
                                             (('alt-1', 'alt-2', 'alt-b'), 'bar')))

        self.widget.keypress((80,), 'alt-b')
        self.assert_status(keys_given=(),
                           widget_text='bar2',
                           active_keychains=())
Esempio n. 2
0
class TestKeyMap_with_single_keys(unittest.TestCase):
    def setUp(self):
        self.km = KeyMap()

    def test_unbind(self):
        self.km.bind(key='a', action='foo')
        self.assertIn(Key('a'), self.km.keys())
        self.km.unbind(key='a')
        self.assertNotIn(Key('a'), self.km.keys())

        self.km.bind(key='b', action='foo')
        with self.assertRaises(ValueError) as cm:
            self.km.unbind(key='c')
        self.assertIn("Key not mapped in context 'default'", str(cm.exception))
        self.assertIn(str(Key('c')), str(cm.exception))

        self.km.bind(key='d', action='foo')
        with self.assertRaises(ValueError) as cm:
            self.km.unbind(key='d', context='bar')
        self.assertIn("Unknown context: 'bar'", str(cm.exception))

        self.km.bind(key='e', action='foo', context='kablam')
        with self.assertRaises(ValueError) as cm:
            self.km.unbind(key='e')
        self.assertIn("Key not mapped in context 'default'", str(cm.exception))
        self.assertIn(str(Key('e')), str(cm.exception))

    def test_mkkey(self):
        self.assertEqual(self.km.mkkey(Key('x')), Key('x'))
        self.assertEqual(self.km.mkkey(KeyChain('1', '2', '3')),
                         KeyChain('1', '2', '3'))

        self.assertEqual(self.km.mkkey('x'), Key('x'))
        self.assertEqual(self.km.mkkey('x y z'), KeyChain('x', 'y', 'z'))
        self.assertEqual(self.km.mkkey('x+y+z'), KeyChain('x', 'y', 'z'))
        self.assertEqual(self.km.mkkey('x +'), KeyChain('x', '+'))
        self.assertEqual(self.km.mkkey('+ x'), KeyChain('+', 'x'))
        self.assertEqual(self.km.mkkey('x y +'), KeyChain('x', 'y', '+'))
        self.assertEqual(self.km.mkkey('+ y z'), KeyChain('+', 'y', 'z'))
        self.assertEqual(self.km.mkkey('+ + +'), KeyChain('+', '+', '+'))

    def test_circular_bind_detection(self):
        with self.assertRaises(ValueError) as cm:
            self.km.bind(key='a', action=self.km.mkkey('a'))
        self.assertIn('Circular', str(cm.exception))
        self.assertIn('<a>', str(cm.exception))

    def test_key_translation(self):
        widget = self.km.wrap(urwid.Text)('Test Text')
        self.km.bind(key='a',
                     action=lambda widget: widget.set_text('Key pressed: a'))
        self.km.bind(key='b', action=Key('a'))
        widget.keypress((80,), 'b')
        self.assertEqual(widget.text, 'Key pressed: a')

    def test_key_translation_to_builtin_key(self):
        class SelectableText(urwid.Text):
            def selectable(self): return True
            def keypress(self, size, key): return key
        list_contents = [SelectableText(str(i)) for i in range(1, 10)]
        listw = self.km.wrap(urwid.ListBox, context='list')(urwid.SimpleFocusListWalker(list_contents))
        self.km.bind(key='j', action=Key('down'))
        self.assertEqual(listw.focus_position, 0)
        listw.keypress((3, 3), 'j')
        self.assertEqual(listw.focus_position, 1)

    def test_action_is_callback(self):
        self.km.bind(key='a',
                     action=lambda widget: widget.set_text('foo'))
        widget = self.km.wrap(urwid.Text)('Test Text')
        widget.keypress((80,), 'a')
        self.assertEqual(widget.text, 'foo')

    def test_widget_callback(self):
        def cb(action, widget):
            widget.set_text(action)

        self.km.bind(key='a', action='foo')
        widget = self.km.wrap(urwid.Text, callback=cb)('Test Text')
        widget.keypress((80,), 'a')
        self.assertEqual(widget.text, 'foo')

    def test_default_callback(self):
        def cb(action, widget):
            widget.set_text(action)

        self.km = KeyMap(callback=cb)
        self.km.bind(key='a', action='foo')
        widget = self.km.wrap(urwid.Text)('Test Text')
        widget.keypress((80,), 'a')
        self.assertEqual(widget.text, 'foo')

    def test_widget_callback_overrides_default_callback(self):
        def default_cb(action, widget):
            widget.set_text(action)

        def widget_cb(action, widget):
            widget.set_text(action.upper())

        self.km = KeyMap(callback=default_cb)
        self.km.bind(key='a', action='foo')
        widget = self.km.wrap(urwid.Text, callback=widget_cb)('Test Text')
        widget.keypress((80,), 'a')
        self.assertEqual(widget.text, 'FOO')