Author terry.reedy
Recipients serhiy.storchaka, terry.reedy
Date 2016-01-22.06:51:27
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1453445489.52.0.0197706093826.issue26177@psf.upfronthosting.co.za>
In-reply-to
Content
tkinter wraps tk widgets as option-value mappings with subscripting and .keys().  The latter does not work for Canvas (subscripting does).  First tested with 3.5.1, Win 10. First Text versus Canvas contrast below was confirmed with 2.7.11.

>>> import tkinter as tk
>>> tk.Text().keys()
['autoseparators', 'background', 'bd', 'bg', 'blockcursor', 'tabstyle', 
...
'takefocus', 'undo', 'width', 'wrap', 'xscrollcommand', 'yscrollcommand']
>>> tk.Canvas().keys()
['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']

Explanation: Widget classes inherit keys from Misc via BaseWidget and Widget.  Misc.keys calls into tk.

    def keys(self):
        """Return a list of all resource names of this widget."""
        return [x[0][1:] for x in
                self.tk.splitlist(self.tk.call(self._w, 'configure'))]

The call returns different types for Text and Canvas.

>>> self = tk.Text()
>>> self.tk.call(self._w, 'configure')  # tuple of tuples
(('-autoseparators', 'autoSeparators', 'AutoSeparators', 1, 1),
 ('-background', 'background', 'Background', <border object: 'SystemWindow'>, 'SystemWindow'), <etc>)
>>> self = tk.Canvas()
>>> self.tk.call(self._w, 'configure')  # tcl list as single string
'{-background background Background SystemButtonFace SystemButtonFace} {-bd borderWidth} {-bg background} {-borderwidth borderWidth BorderWidth 0 0} ...'

This difference between widgets seems odd.  A bug in tcl/tk/_tkinter?

tk.splitlist appears to return the Text tuple of tuples as is.  It splits the Canvas string into a tuple of strings

('-background background Background SystemButtonFace SystemButtonFace', '-bd borderWidth', ... )

but does not split the inner strings.  As a consequence, x[0] is the first character of each string ('{' as it turns out, though not relevant) and the slice [1:] of a single char string is always ''.

Possible remedy: tk.split also leaves tuple of tuples alone *and* splits the inner strings to a tuple.

>>> self.tk.split(self.tk.call(self._w, 'configure'))
(('-background', 'background', 'Background', 'SystemButtonFace', 'red'), ('-bd', 'borderWidth'), ...)

So a fix (if the different returns are not changed) is to change 'splitlines' to 'split'.  With this change, keys (extracted as a function) gives the expected list.

>>> keys(tk.Canvas())
['background', 'bd', ..., 'yscrollincrement']

A test for Canvas().keys should be added somewhere.
History
Date User Action Args
2016-01-22 06:51:29terry.reedysetrecipients: + terry.reedy, serhiy.storchaka
2016-01-22 06:51:29terry.reedysetmessageid: <1453445489.52.0.0197706093826.issue26177@psf.upfronthosting.co.za>
2016-01-22 06:51:29terry.reedylinkissue26177 messages
2016-01-22 06:51:27terry.reedycreate