[Idle-dev] KeyConfig, KeyBinding and other related issues.

Terry Reedy tjreedy at udel.edu
Mon Jun 16 04:05:59 CEST 2014

On 6/15/2014 7:53 AM, Saimadhav Heblikar wrote:
> Hi,
> I followed the above direction and made some progress.
> Lib/tkinter/__init__.py Line 998, gives some more info on the syntax
> for keysequence.
> https://gist.github.com/sahutd/289d2297eb83a020a6dd#file-test-keyseq-v2-diff.
> It only covers a few exceptions. I am posting this early, before I am
> far away in the wrong direction.
> Also, is the key_ok method intended as a replacement for the existing
> KeysOk method? Or are both going to exist?

My thoughts as of this evening:

What we want is a broader check function usable in multiple places. 
Whatever you write for testing may need to be modified for use in 
multiple places. If we imagine putting a module-level function into 
KeybindingDialog.py, definitions of constants (in LaodFinalKeyList and 
TranslateKey) could be moved from class to module scope to make them 
available to a new check function. The TranslateKey methods could also 
be elevated, as it has no dependence on 'self' and is not really an 
instance method.

Parameterless KeysOK is specific to and intertwined with the basic 
dialog (which is why it can work without overt inputs). Since it mostly 
works with the pieces used to create the keystring, it avoids parsing 
the keystrings (which is why it cannot work with advanced mode). This 
make it awful to test, compared with a function that take the keystring 
as a parameter and parses it without other info.

After the keystring is fetched, the rest of the body could be replaced 
with a call to a function that *does* parse. But that is not important 
either way at the moment.

Since KeysOK shows at most one error message, the tkMessagebox call
could be factored out of the switch, with each branch setting msg
(else: would set it to ''). Then add at the end

  'if msg:
         parent=self, title='Key Sequence Error',
         message='Keystring {}: {}'.format(keys, msg))

I might actually do this.

Once done, the logic of KeysOK could be inverted to KeysNotOk (or 
KeysBad) by returning msg. The caller could replace 'self.KeysOk' with 
'not self.KeysBad'.

And additional refinement would make KeysBad even easier to test: a 
dictionary of error messages (which also makes it easy to see the 
conditions tested).

keyerrors = {
   'empty' : 'no keys specified.',
   'end' : 'missing the final Key'.
   'mod' : 'no modifier key(s) specified.'.
   'shift' : 'the shift modifier by itself may not be used with'
              ' this key symbol.'.
   'dup' : 'this key combination is already in use.',

Now, if KeysBad sets messages with statements like
     if not keys: msg = keyerrors['empty']
a test such as
     self.assertIn(keyerrors['empty'], KeysBad(''))
is not only clear and easy to write, but is also robust against message 
edits in the one and only location, the dictionary.

As you might have guessed, I am writing the above to answer your 
question below.

keyerrors = {

def key_bad(keystring, showerror=True):  # False in test files
   <test and set msg if error>
   if msg and showerror: tkMessage....
   return msg

If you decide or plan to detect and report multiple errors, the details 
of message construction can be altered.

When Idle initializes from .def files, keystrings should first be given 
to tk, as now, and the check function only used to display an error 
message after catching tcl_error. If key_bad returns '' when tk has 
rejected it, display a backup message: 'tk rejects %s, but we cannot 
determine why' % keystring.

> On 14 June 2014 15:46, Tal Einat <taleinat at gmail.com> wrote:
>> To give a bit more direction on the implementation, the steps for the
>> parsing function should be roughly:
>> 1) basic parsing: remove '<' and '>' and ends and split by '_'.

Perhaps the person who suggested a finite automaton was suggesting 
transitions based on words after such a split, rather than character 
based transitions, as with re engines. My main concern is that errors 
get detected and reported.

>> 2) group parts into the three groups while checking that they are
>> valid (not empty, etc.)

> Grouping required a single line of regex.
> pat = '^<(?P<modifiers>(({modifier})-){{0,3}})(({type})-)?({detail})>$'.format(modifier=modifier_regex,type=type_regex,
> detail=detail_regex)
>> 3) return the groups
>> Each step should give an informative message if an error is encountered.

> For the above point, should key_ok method raise an error or return
> False or display a tkMessageBox ?

See above.

Terry Jan Reedy

More information about the IDLE-dev mailing list