"""
from tkinter import *
from tkinter.ttk import Scrollbar
-import tkinter.messagebox as tkMessageBox
+from tkinter import messagebox
import string
import sys
+
class GetKeysDialog(Toplevel):
+
+ # Dialog title for invalid key sequence
+ keyerror_title = 'Key Sequence Error'
+
def __init__(self, parent, title, action, currentKeySequences,
_htest=False, _utest=False):
"""
self.deiconify() #geometry set, unhide
self.wait_window()
+ def showerror(self, *args, **kwargs):
+ # Make testing easier. Replace in #30751.
+ messagebox.showerror(*args, **kwargs)
+
def CreateWidgets(self):
frameMain = Frame(self,borderwidth=2,relief=SUNKEN)
frameMain.pack(side=TOP,expand=TRUE,fill=BOTH)
return key
def OK(self, event=None):
- if self.advanced or self.KeysOK(): # doesn't check advanced string yet
- self.result=self.keyString.get()
- self.destroy()
+ keys = self.keyString.get().strip()
+ if not keys:
+ self.showerror(title=self.keyerror_title, parent=self,
+ message="No key specified.")
+ return
+ if (self.advanced or self.KeysOK(keys)) and self.bind_ok(keys):
+ self.result = keys
+ self.destroy()
def Cancel(self, event=None):
self.result=''
self.destroy()
- def KeysOK(self):
+ def KeysOK(self, keys):
'''Validity check on user's 'basic' keybinding selection.
Doesn't check the string produced by the advanced dialog because
'modifiers' isn't set.
'''
- keys = self.keyString.get()
- keys.strip()
finalKey = self.listKeysFinal.get(ANCHOR)
modifiers = self.GetModifiers()
# create a key sequence list for overlap check:
keySequence = keys.split()
keysOK = False
- title = 'Key Sequence Error'
- if not keys:
- tkMessageBox.showerror(title=title, parent=self,
- message='No keys specified.')
- elif not keys.endswith('>'):
- tkMessageBox.showerror(title=title, parent=self,
- message='Missing the final Key')
+ title = self.keyerror_title
+ if not keys.endswith('>'):
+ self.showerror(title, parent=self,
+ message='Missing the final Key')
elif (not modifiers
and finalKey not in self.functionKeys + self.moveKeys):
- tkMessageBox.showerror(title=title, parent=self,
- message='No modifier key(s) specified.')
+ self.showerror(title=title, parent=self,
+ message='No modifier key(s) specified.')
elif (modifiers == ['Shift']) \
and (finalKey not in
self.functionKeys + self.moveKeys + ('Tab', 'Space')):
msg = 'The shift modifier by itself may not be used with'\
' this key symbol.'
- tkMessageBox.showerror(title=title, parent=self, message=msg)
+ self.showerror(title=title, parent=self, message=msg)
elif keySequence in self.currentKeySequences:
msg = 'This key combination is already in use.'
- tkMessageBox.showerror(title=title, parent=self, message=msg)
+ self.showerror(title=title, parent=self, message=msg)
else:
keysOK = True
return keysOK
+ def bind_ok(self, keys):
+ "Return True if Tcl accepts the new keys else show message."
+
+ try:
+ binding = self.bind(keys, lambda: None)
+ except TclError as err:
+ self.showerror(
+ title=self.keyerror_title, parent=self,
+ message=(f'The entered key sequence is not accepted.\n\n'
+ f'Error: {err}'))
+ return False
+ else:
+ self.unbind(keys, binding)
+ return True
+
if __name__ == '__main__':
+ import unittest
+ unittest.main('idlelib.idle_test.test_config_key', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(GetKeysDialog)
'''
from idlelib import config_key
from test.support import requires
-requires('gui')
+import sys
import unittest
from tkinter import Tk
+from idlelib.idle_test.mock_idle import Func
+from idlelib.idle_test.mock_tk import Var, Mbox_func
-class GetKeysTest(unittest.TestCase):
+class ValidationTest(unittest.TestCase):
+ "Test validation methods: OK, KeysOK, bind_ok."
+
+ class Validator(config_key.GetKeysDialog):
+ def __init__(self, *args, **kwargs):
+ config_key.GetKeysDialog.__init__(self, *args, **kwargs)
+ class listKeysFinal:
+ get = Func()
+ self.listKeysFinal = listKeysFinal
+ GetModifiers = Func()
+ showerror = Mbox_func()
@classmethod
def setUpClass(cls):
+ requires('gui')
cls.root = Tk()
cls.root.withdraw()
+ cls.dialog = cls.Validator(
+ cls.root, 'Title', '<<Test>>', [['<Key-F12>']], _utest=True)
@classmethod
def tearDownClass(cls):
- cls.root.update() # Stop "can't run event command" warning.
+ cls.dialog.Cancel()
+ cls.root.update_idletasks()
cls.root.destroy()
- del cls.root
+ del cls.dialog, cls.root
+
+ def setUp(self):
+ self.dialog.showerror.message = ''
+ # A test that needs a particular final key value should set it.
+ # A test that sets a non-blank modifier list should reset it to [].
+
+ def test_ok_empty(self):
+ self.dialog.keyString.set(' ')
+ self.dialog.OK()
+ self.assertEqual(self.dialog.result, '')
+ self.assertEqual(self.dialog.showerror.message, 'No key specified.')
+
+ def test_ok_good(self):
+ self.dialog.keyString.set('<Key-F11>')
+ self.dialog.listKeysFinal.get.result = 'F11'
+ self.dialog.OK()
+ self.assertEqual(self.dialog.result, '<Key-F11>')
+ self.assertEqual(self.dialog.showerror.message, '')
+
+ def test_keys_no_ending(self):
+ self.assertFalse(self.dialog.KeysOK('<Control-Shift'))
+ self.assertIn('Missing the final', self.dialog.showerror.message)
+
+ def test_keys_no_modifier_bad(self):
+ self.dialog.listKeysFinal.get.result = 'A'
+ self.assertFalse(self.dialog.KeysOK('<Key-A>'))
+ self.assertIn('No modifier', self.dialog.showerror.message)
+
+ def test_keys_no_modifier_ok(self):
+ self.dialog.listKeysFinal.get.result = 'F11'
+ self.assertTrue(self.dialog.KeysOK('<Key-F11>'))
+ self.assertEqual(self.dialog.showerror.message, '')
+
+ def test_keys_shift_bad(self):
+ self.dialog.listKeysFinal.get.result = 'a'
+ self.dialog.GetModifiers.result = ['Shift']
+ self.assertFalse(self.dialog.KeysOK('<a>'))
+ self.assertIn('shift modifier', self.dialog.showerror.message)
+ self.dialog.GetModifiers.result = []
+
+ def test_keys_dup(self):
+ self.dialog.listKeysFinal.get.result = 'F12'
+ self.dialog.GetModifiers.result = []
+ self.assertFalse(self.dialog.KeysOK('<Key-F12>'))
+ self.assertIn('already in use', self.dialog.showerror.message)
+ def test_bind_ok(self):
+ self.assertTrue(self.dialog.bind_ok('<Control-Shift-Key-a>'))
+ self.assertEqual(self.dialog.showerror.message, '')
- def test_init(self):
- dia = config_key.GetKeysDialog(
- self.root, 'test', '<<Test>>', ['<Key-F12>'], _utest=True)
- dia.Cancel()
+ def test_bind_not_ok(self):
+ self.assertFalse(self.dialog.bind_ok('<Control-Shift>'))
+ self.assertIn('not accepted', self.dialog.showerror.message)
if __name__ == '__main__':