Issue #20072: Fixed multiple errors in tkinter with wantobjects is False.

* Misc.image_names(), Misc.image_types(), Wm.wm_colormapwindows(), and
  LabelFrame.panes() now always return a tuple.
* Fixed error of comparing str and int in tt.LabeledScale._adjust().
* ttk.Notebook.index() now always returns int.
* ttk.Notebook.tabs() now always returns a tuple.
* ttk.Entry.bbox() now always returns a tuple of ints.
* ttk.Entry.validate() now always correctly works.
* ttk.Combobox.current() now always returns int.
* ttk.Panedwindow.sashpos() now always returns int.
* ttk.Treeview.bbox() now always returns a tuple of ints.
* ttk.Treeview.get_children() now always returns a tuple.
* ttk.Treeview.exists() now always correctly works.
* ttk.Treeview.index() now always returns int.
* ttk.Treeview.tag_has() now always returns 0 or 1.
* And numerous other errors in methods which returns a tuple, list or dict.
* Fixed ttk tests for wantobjects is False.
This commit is contained in:
Serhiy Storchaka 2014-01-07 19:30:36 +02:00
commit 985b8dbe11
7 changed files with 153 additions and 71 deletions

View file

@ -1459,11 +1459,11 @@ class Misc:
def image_names(self): def image_names(self):
"""Return a list of all existing image names.""" """Return a list of all existing image names."""
return self.tk.call('image', 'names') return self.tk.splitlist(self.tk.call('image', 'names'))
def image_types(self): def image_types(self):
"""Return a list of all available image types (e.g. phote bitmap).""" """Return a list of all available image types (e.g. phote bitmap)."""
return self.tk.call('image', 'types') return self.tk.splitlist(self.tk.call('image', 'types'))
class CallWrapper: class CallWrapper:
@ -1577,7 +1577,11 @@ class Wm:
if len(wlist) > 1: if len(wlist) > 1:
wlist = (wlist,) # Tk needs a list of windows here wlist = (wlist,) # Tk needs a list of windows here
args = ('wm', 'colormapwindows', self._w) + wlist args = ('wm', 'colormapwindows', self._w) + wlist
return [self._nametowidget(x) for x in self.tk.call(args)] if wlist:
self.tk.call(args)
else:
return [self._nametowidget(x)
for x in self.tk.splitlist(self.tk.call(args))]
colormapwindows = wm_colormapwindows colormapwindows = wm_colormapwindows
def wm_command(self, value=None): def wm_command(self, value=None):
"""Store VALUE in WM_COMMAND property. It is the command """Store VALUE in WM_COMMAND property. It is the command
@ -3433,8 +3437,11 @@ class BitmapImage(Image):
Valid resource names: background, data, file, foreground, maskdata, maskfile.""" Valid resource names: background, data, file, foreground, maskdata, maskfile."""
Image.__init__(self, 'bitmap', name, cnf, master, **kw) Image.__init__(self, 'bitmap', name, cnf, master, **kw)
def image_names(): return _default_root.tk.call('image', 'names') def image_names():
def image_types(): return _default_root.tk.call('image', 'types') return _default_root.tk.splitlist(_default_root.tk.call('image', 'names'))
def image_types():
return _default_root.tk.splitlist(_default_root.tk.call('image', 'types'))
class Spinbox(Widget, XView): class Spinbox(Widget, XView):
@ -3803,7 +3810,7 @@ class PanedWindow(Widget):
def panes(self): def panes(self):
"""Returns an ordered list of the child panes.""" """Returns an ordered list of the child panes."""
return self.tk.call(self._w, 'panes') return self.tk.splitlist(self.tk.call(self._w, 'panes'))
###################################################################### ######################################################################
# Extensions: # Extensions:

View file

@ -29,7 +29,10 @@ class LabeledScaleTest(unittest.TestCase):
name = myvar._name name = myvar._name
x = ttk.LabeledScale(variable=myvar) x = ttk.LabeledScale(variable=myvar)
x.destroy() x.destroy()
self.assertEqual(x.tk.globalgetvar(name), myvar.get()) if x.tk.wantobjects():
self.assertEqual(x.tk.globalgetvar(name), myvar.get())
else:
self.assertEqual(float(x.tk.globalgetvar(name)), myvar.get())
del myvar del myvar
self.assertRaises(tkinter.TclError, x.tk.globalgetvar, name) self.assertRaises(tkinter.TclError, x.tk.globalgetvar, name)
@ -59,8 +62,10 @@ class LabeledScaleTest(unittest.TestCase):
x.destroy() x.destroy()
# variable initialization/passing # variable initialization/passing
passed_expected = ((2.5, 2), ('0', 0), (0, 0), (10, 10), passed_expected = (('0', 0), (0, 0), (10, 10),
(-1, -1), (sys.maxsize + 1, sys.maxsize + 1)) (-1, -1), (sys.maxsize + 1, sys.maxsize + 1))
if x.tk.wantobjects():
passed_expected += ((2.5, 2),)
for pair in passed_expected: for pair in passed_expected:
x = ttk.LabeledScale(from_=pair[0]) x = ttk.LabeledScale(from_=pair[0])
self.assertEqual(x.value, pair[1]) self.assertEqual(x.value, pair[1])
@ -123,7 +128,7 @@ class LabeledScaleTest(unittest.TestCase):
self.assertNotEqual(prev_xcoord, curr_xcoord) self.assertNotEqual(prev_xcoord, curr_xcoord)
# the label widget should have been repositioned too # the label widget should have been repositioned too
linfo_2 = lscale.label.place_info() linfo_2 = lscale.label.place_info()
self.assertEqual(lscale.label['text'], 0) self.assertEqual(lscale.label['text'], 0 if lscale.tk.wantobjects() else '0')
self.assertEqual(curr_xcoord, int(linfo_2['x'])) self.assertEqual(curr_xcoord, int(linfo_2['x']))
# change the range back # change the range back
lscale.scale.configure(from_=0, to=10) lscale.scale.configure(from_=0, to=10)
@ -145,15 +150,20 @@ class LabeledScaleTest(unittest.TestCase):
# The following update is needed since the test doesn't use mainloop, # The following update is needed since the test doesn't use mainloop,
# at the same time this shouldn't affect test outcome # at the same time this shouldn't affect test outcome
x.update() x.update()
self.assertEqual(x.label['text'], newval) self.assertEqual(x.label['text'],
newval if x.tk.wantobjects() else str(newval))
self.assertGreater(x.scale.coords()[0], curr_xcoord) self.assertGreater(x.scale.coords()[0], curr_xcoord)
self.assertEqual(x.scale.coords()[0], self.assertEqual(x.scale.coords()[0],
int(x.label.place_info()['x'])) int(x.label.place_info()['x']))
# value outside range # value outside range
x.value = x.scale['to'] + 1 # no changes shouldn't happen if x.tk.wantobjects():
conv = lambda x: x
else:
conv = int
x.value = conv(x.scale['to']) + 1 # no changes shouldn't happen
x.update() x.update()
self.assertEqual(x.label['text'], newval) self.assertEqual(conv(x.label['text']), newval)
self.assertEqual(x.scale.coords()[0], self.assertEqual(x.scale.coords()[0],
int(x.label.place_info()['x'])) int(x.label.place_info()['x']))

View file

@ -393,8 +393,10 @@ class InternalFunctionsTest(unittest.TestCase):
('name', 'no_minus', 'value')) ('name', 'no_minus', 'value'))
self.assertRaises(ValueError, ttk._list_from_layouttuple, self.assertRaises(ValueError, ttk._list_from_layouttuple,
('something', '-children')) # no children ('something', '-children')) # no children
self.assertRaises(ValueError, ttk._list_from_layouttuple, import tkinter
('something', '-children', 'value')) # invalid children if not tkinter._default_root or tkinter._default_root.wantobjects():
self.assertRaises(ValueError, ttk._list_from_layouttuple,
('something', '-children', 'value')) # invalid children
def test_val_or_dict(self): def test_val_or_dict(self):

View file

@ -25,7 +25,8 @@ class StyleTest(unittest.TestCase):
style = self.style style = self.style
style.map('TButton', background=[('active', 'background', 'blue')]) style.map('TButton', background=[('active', 'background', 'blue')])
self.assertEqual(style.map('TButton', 'background'), self.assertEqual(style.map('TButton', 'background'),
[('active', 'background', 'blue')]) [('active', 'background', 'blue')] if style.tk.wantobjects() else
[('active background', 'blue')])
self.assertIsInstance(style.map('TButton'), dict) self.assertIsInstance(style.map('TButton'), dict)

View file

@ -382,15 +382,21 @@ class ComboboxTest(AbstractWidgetTest, unittest.TestCase):
# testing values with empty string set through configure # testing values with empty string set through configure
self.combo.configure(values=[1, '', 2]) self.combo.configure(values=[1, '', 2])
self.assertEqual(self.combo['values'], ('1', '', '2')) self.assertEqual(self.combo['values'],
('1', '', '2') if self.wantobjects else
'1 {} 2')
# testing values with spaces # testing values with spaces
self.combo['values'] = ['a b', 'a\tb', 'a\nb'] self.combo['values'] = ['a b', 'a\tb', 'a\nb']
self.assertEqual(self.combo['values'], ('a b', 'a\tb', 'a\nb')) self.assertEqual(self.combo['values'],
('a b', 'a\tb', 'a\nb') if self.wantobjects else
'{a b} {a\tb} {a\nb}')
# testing values with special characters # testing values with special characters
self.combo['values'] = [r'a\tb', '"a"', '} {'] self.combo['values'] = [r'a\tb', '"a"', '} {']
self.assertEqual(self.combo['values'], (r'a\tb', '"a"', '} {')) self.assertEqual(self.combo['values'],
(r'a\tb', '"a"', '} {') if self.wantobjects else
r'a\\tb {"a"} \}\ \{')
# out of range # out of range
self.assertRaises(tkinter.TclError, self.combo.current, self.assertRaises(tkinter.TclError, self.combo.current,
@ -400,7 +406,8 @@ class ComboboxTest(AbstractWidgetTest, unittest.TestCase):
# testing creating combobox with empty string in values # testing creating combobox with empty string in values
combo2 = ttk.Combobox(values=[1, 2, '']) combo2 = ttk.Combobox(values=[1, 2, ''])
self.assertEqual(combo2['values'], ('1', '2', '')) self.assertEqual(combo2['values'],
('1', '2', '') if self.wantobjects else '1 2 {}')
combo2.destroy() combo2.destroy()
@ -654,9 +661,11 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
child = ttk.Label() child = ttk.Label()
self.paned.add(child) self.paned.add(child)
self.assertIsInstance(self.paned.pane(0), dict) self.assertIsInstance(self.paned.pane(0), dict)
self.assertEqual(self.paned.pane(0, weight=None), 0) self.assertEqual(self.paned.pane(0, weight=None),
0 if self.wantobjects else '0')
# newer form for querying a single option # newer form for querying a single option
self.assertEqual(self.paned.pane(0, 'weight'), 0) self.assertEqual(self.paned.pane(0, 'weight'),
0 if self.wantobjects else '0')
self.assertEqual(self.paned.pane(0), self.paned.pane(str(child))) self.assertEqual(self.paned.pane(0), self.paned.pane(str(child)))
self.assertRaises(tkinter.TclError, self.paned.pane, 0, self.assertRaises(tkinter.TclError, self.paned.pane, 0,
@ -711,20 +720,25 @@ class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
cbtn = ttk.Radiobutton(command=cb_test, variable=myvar, value=0) cbtn = ttk.Radiobutton(command=cb_test, variable=myvar, value=0)
cbtn2 = ttk.Radiobutton(command=cb_test, variable=myvar, value=1) cbtn2 = ttk.Radiobutton(command=cb_test, variable=myvar, value=1)
if self.wantobjects:
conv = lambda x: x
else:
conv = int
res = cbtn.invoke() res = cbtn.invoke()
self.assertEqual(res, "cb test called") self.assertEqual(res, "cb test called")
self.assertEqual(cbtn['value'], myvar.get()) self.assertEqual(conv(cbtn['value']), myvar.get())
self.assertEqual(myvar.get(), self.assertEqual(myvar.get(),
cbtn.tk.globalgetvar(cbtn['variable'])) conv(cbtn.tk.globalgetvar(cbtn['variable'])))
self.assertTrue(success) self.assertTrue(success)
cbtn2['command'] = '' cbtn2['command'] = ''
res = cbtn2.invoke() res = cbtn2.invoke()
self.assertEqual(str(res), '') self.assertEqual(str(res), '')
self.assertLessEqual(len(success), 1) self.assertLessEqual(len(success), 1)
self.assertEqual(cbtn2['value'], myvar.get()) self.assertEqual(conv(cbtn2['value']), myvar.get())
self.assertEqual(myvar.get(), self.assertEqual(myvar.get(),
cbtn.tk.globalgetvar(cbtn['variable'])) conv(cbtn.tk.globalgetvar(cbtn['variable'])))
self.assertEqual(str(cbtn['variable']), str(cbtn2['variable'])) self.assertEqual(str(cbtn['variable']), str(cbtn2['variable']))
@ -812,10 +826,15 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
def test_get(self): def test_get(self):
if self.wantobjects:
conv = lambda x: x
else:
conv = float
scale_width = self.scale.winfo_width() scale_width = self.scale.winfo_width()
self.assertEqual(self.scale.get(scale_width, 0), self.scale['to']) self.assertEqual(self.scale.get(scale_width, 0), self.scale['to'])
self.assertEqual(self.scale.get(0, 0), self.scale['from']) self.assertEqual(conv(self.scale.get(0, 0)), conv(self.scale['from']))
self.assertEqual(self.scale.get(), self.scale['value']) self.assertEqual(self.scale.get(), self.scale['value'])
self.scale['value'] = 30 self.scale['value'] = 30
self.assertEqual(self.scale.get(), self.scale['value']) self.assertEqual(self.scale.get(), self.scale['value'])
@ -825,32 +844,37 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
def test_set(self): def test_set(self):
if self.wantobjects:
conv = lambda x: x
else:
conv = float
# set restricts the max/min values according to the current range # set restricts the max/min values according to the current range
max = self.scale['to'] max = conv(self.scale['to'])
new_max = max + 10 new_max = max + 10
self.scale.set(new_max) self.scale.set(new_max)
self.assertEqual(self.scale.get(), max) self.assertEqual(conv(self.scale.get()), max)
min = self.scale['from'] min = conv(self.scale['from'])
self.scale.set(min - 1) self.scale.set(min - 1)
self.assertEqual(self.scale.get(), min) self.assertEqual(conv(self.scale.get()), min)
# changing directly the variable doesn't impose this limitation tho # changing directly the variable doesn't impose this limitation tho
var = tkinter.DoubleVar() var = tkinter.DoubleVar()
self.scale['variable'] = var self.scale['variable'] = var
var.set(max + 5) var.set(max + 5)
self.assertEqual(self.scale.get(), var.get()) self.assertEqual(conv(self.scale.get()), var.get())
self.assertEqual(self.scale.get(), max + 5) self.assertEqual(conv(self.scale.get()), max + 5)
del var del var
# the same happens with the value option # the same happens with the value option
self.scale['value'] = max + 10 self.scale['value'] = max + 10
self.assertEqual(self.scale.get(), max + 10) self.assertEqual(conv(self.scale.get()), max + 10)
self.assertEqual(self.scale.get(), self.scale['value']) self.assertEqual(conv(self.scale.get()), conv(self.scale['value']))
# nevertheless, note that the max/min values we can get specifying # nevertheless, note that the max/min values we can get specifying
# x, y coords are the ones according to the current range # x, y coords are the ones according to the current range
self.assertEqual(self.scale.get(0, 0), min) self.assertEqual(conv(self.scale.get(0, 0)), min)
self.assertEqual(self.scale.get(self.scale.winfo_width(), 0), max) self.assertEqual(conv(self.scale.get(self.scale.winfo_width(), 0)), max)
self.assertRaises(tkinter.TclError, self.scale.set, None) self.assertRaises(tkinter.TclError, self.scale.set, None)
@ -1204,6 +1228,8 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
self.tv.column('test', width=50) self.tv.column('test', width=50)
bbox_column0 = self.tv.bbox(children[0], 0) bbox_column0 = self.tv.bbox(children[0], 0)
root_width = self.tv.column('#0', width=None) root_width = self.tv.column('#0', width=None)
if not self.wantobjects:
root_width = int(root_width)
self.assertEqual(bbox_column0[0], bbox[0] + root_width) self.assertEqual(bbox_column0[0], bbox[0] + root_width)
# verify that bbox of a closed item is the empty string # verify that bbox of a closed item is the empty string
@ -1243,12 +1269,15 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
# return a dict with all options/values # return a dict with all options/values
self.assertIsInstance(self.tv.column('#0'), dict) self.assertIsInstance(self.tv.column('#0'), dict)
# return a single value of the given option # return a single value of the given option
self.assertIsInstance(self.tv.column('#0', width=None), int) if self.wantobjects:
self.assertIsInstance(self.tv.column('#0', width=None), int)
# set a new value for an option # set a new value for an option
self.tv.column('#0', width=10) self.tv.column('#0', width=10)
# testing new way to get option value # testing new way to get option value
self.assertEqual(self.tv.column('#0', 'width'), 10) self.assertEqual(self.tv.column('#0', 'width'),
self.assertEqual(self.tv.column('#0', width=None), 10) 10 if self.wantobjects else '10')
self.assertEqual(self.tv.column('#0', width=None),
10 if self.wantobjects else '10')
# check read-only option # check read-only option
self.assertRaises(tkinter.TclError, self.tv.column, '#0', id='X') self.assertRaises(tkinter.TclError, self.tv.column, '#0', id='X')
@ -1461,11 +1490,14 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
# unicode values # unicode values
value = '\xe1ba' value = '\xe1ba'
item = self.tv.insert('', 'end', values=(value, )) item = self.tv.insert('', 'end', values=(value, ))
self.assertEqual(self.tv.item(item, 'values'), (value, )) self.assertEqual(self.tv.item(item, 'values'),
self.assertEqual(self.tv.item(item, values=None), (value, )) (value,) if self.wantobjects else value)
self.assertEqual(self.tv.item(item, values=None),
(value,) if self.wantobjects else value)
self.tv.item(item, values=list(self.tv.item(item, values=None))) self.tv.item(item, values=self.root.splitlist(self.tv.item(item, values=None)))
self.assertEqual(self.tv.item(item, values=None), (value, )) self.assertEqual(self.tv.item(item, values=None),
(value,) if self.wantobjects else value)
self.assertIsInstance(self.tv.item(item), dict) self.assertIsInstance(self.tv.item(item), dict)
@ -1475,17 +1507,21 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
# item tags # item tags
item = self.tv.insert('', 'end', tags=[1, 2, value]) item = self.tv.insert('', 'end', tags=[1, 2, value])
self.assertEqual(self.tv.item(item, tags=None), ('1', '2', value)) self.assertEqual(self.tv.item(item, tags=None),
('1', '2', value) if self.wantobjects else
'1 2 %s' % value)
self.tv.item(item, tags=[]) self.tv.item(item, tags=[])
self.assertFalse(self.tv.item(item, tags=None)) self.assertFalse(self.tv.item(item, tags=None))
self.tv.item(item, tags=(1, 2)) self.tv.item(item, tags=(1, 2))
self.assertEqual(self.tv.item(item, tags=None), ('1', '2')) self.assertEqual(self.tv.item(item, tags=None),
('1', '2') if self.wantobjects else '1 2')
# values with spaces # values with spaces
item = self.tv.insert('', 'end', values=('a b c', item = self.tv.insert('', 'end', values=('a b c',
'%s %s' % (value, value))) '%s %s' % (value, value)))
self.assertEqual(self.tv.item(item, values=None), self.assertEqual(self.tv.item(item, values=None),
('a b c', '%s %s' % (value, value))) ('a b c', '%s %s' % (value, value)) if self.wantobjects else
'{a b c} {%s %s}' % (value, value))
# text # text
self.assertEqual(self.tv.item( self.assertEqual(self.tv.item(
@ -1502,19 +1538,24 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
self.assertEqual(self.tv.set(item), {'A': 'a', 'B': 'b'}) self.assertEqual(self.tv.set(item), {'A': 'a', 'B': 'b'})
self.tv.set(item, 'B', 'a') self.tv.set(item, 'B', 'a')
self.assertEqual(self.tv.item(item, values=None), ('a', 'a')) self.assertEqual(self.tv.item(item, values=None),
('a', 'a') if self.wantobjects else 'a a')
self.tv['columns'] = ['B'] self.tv['columns'] = ['B']
self.assertEqual(self.tv.set(item), {'B': 'a'}) self.assertEqual(self.tv.set(item), {'B': 'a'})
self.tv.set(item, 'B', 'b') self.tv.set(item, 'B', 'b')
self.assertEqual(self.tv.set(item, column='B'), 'b') self.assertEqual(self.tv.set(item, column='B'), 'b')
self.assertEqual(self.tv.item(item, values=None), ('b', 'a')) self.assertEqual(self.tv.item(item, values=None),
('b', 'a') if self.wantobjects else 'b a')
self.tv.set(item, 'B', 123) self.tv.set(item, 'B', 123)
self.assertEqual(self.tv.set(item, 'B'), 123) self.assertEqual(self.tv.set(item, 'B'),
self.assertEqual(self.tv.item(item, values=None), (123, 'a')) 123 if self.wantobjects else '123')
self.assertEqual(self.tv.set(item), {'B': 123}) self.assertEqual(self.tv.item(item, values=None),
(123, 'a') if self.wantobjects else '123 a')
self.assertEqual(self.tv.set(item),
{'B': 123} if self.wantobjects else {'B': '123'})
# inexistent column # inexistent column
self.assertRaises(tkinter.TclError, self.tv.set, item, 'A') self.assertRaises(tkinter.TclError, self.tv.set, item, 'A')

View file

@ -293,6 +293,9 @@ def _list_from_layouttuple(ltuple):
indx += 2 indx += 2
if opt == 'children': if opt == 'children':
if (tkinter._default_root and
not tkinter._default_root.wantobjects()):
val = tkinter._default_root.splitlist(val)
val = _list_from_layouttuple(val) val = _list_from_layouttuple(val)
opts[opt] = val opts[opt] = val
@ -313,6 +316,8 @@ def _val_or_dict(options, func, *args):
if len(options) % 2: # option specified without a value, return its value if len(options) % 2: # option specified without a value, return its value
return res return res
if tkinter._default_root:
res = tkinter._default_root.splitlist(res)
return _dict_from_tcltuple(res) return _dict_from_tcltuple(res)
def _convert_stringval(value): def _convert_stringval(value):
@ -325,6 +330,14 @@ def _convert_stringval(value):
return value return value
def _to_number(x):
if isinstance(x, str):
if '.' in x:
x = float(x)
else:
x = int(x)
return x
def tclobjs_to_py(adict): def tclobjs_to_py(adict):
"""Returns adict with its values converted from Tcl objects to Python """Returns adict with its values converted from Tcl objects to Python
objects.""" objects."""
@ -395,8 +408,8 @@ class Style(object):
or something else of your preference. A statespec is compound of or something else of your preference. A statespec is compound of
one or more states and then a value.""" one or more states and then a value."""
if query_opt is not None: if query_opt is not None:
return _list_from_statespec( return _list_from_statespec(self.tk.splitlist(
self.tk.call(self._name, "map", style, '-%s' % query_opt)) self.tk.call(self._name, "map", style, '-%s' % query_opt)))
return _dict_from_tcltuple( return _dict_from_tcltuple(
self.tk.call(self._name, "map", style, *(_format_mapdict(kw)))) self.tk.call(self._name, "map", style, *(_format_mapdict(kw))))
@ -453,8 +466,8 @@ class Style(object):
lspec = "null" # could be any other word, but this may make sense lspec = "null" # could be any other word, but this may make sense
# when calling layout(style) later # when calling layout(style) later
return _list_from_layouttuple( return _list_from_layouttuple(self.tk.splitlist(
self.tk.call(self._name, "layout", style, lspec)) self.tk.call(self._name, "layout", style, lspec)))
def element_create(self, elementname, etype, *args, **kw): def element_create(self, elementname, etype, *args, **kw):
@ -466,12 +479,12 @@ class Style(object):
def element_names(self): def element_names(self):
"""Returns the list of elements defined in the current theme.""" """Returns the list of elements defined in the current theme."""
return self.tk.call(self._name, "element", "names") return self.tk.splitlist(self.tk.call(self._name, "element", "names"))
def element_options(self, elementname): def element_options(self, elementname):
"""Return the list of elementname's options.""" """Return the list of elementname's options."""
return self.tk.call(self._name, "element", "options", elementname) return self.tk.splitlist(self.tk.call(self._name, "element", "options", elementname))
def theme_create(self, themename, parent=None, settings=None): def theme_create(self, themename, parent=None, settings=None):
@ -505,7 +518,7 @@ class Style(object):
def theme_names(self): def theme_names(self):
"""Returns a list of all known themes.""" """Returns a list of all known themes."""
return self.tk.call(self._name, "theme", "names") return self.tk.splitlist(self.tk.call(self._name, "theme", "names"))
def theme_use(self, themename=None): def theme_use(self, themename=None):
@ -568,7 +581,8 @@ class Widget(tkinter.Widget):
matches statespec and False otherwise. If callback is specified, matches statespec and False otherwise. If callback is specified,
then it will be invoked with *args, **kw if the widget state then it will be invoked with *args, **kw if the widget state
matches statespec. statespec is expected to be a sequence.""" matches statespec. statespec is expected to be a sequence."""
ret = self.tk.call(self._w, "instate", ' '.join(statespec)) ret = self.tk.getboolean(
self.tk.call(self._w, "instate", ' '.join(statespec)))
if ret and callback: if ret and callback:
return callback(*args, **kw) return callback(*args, **kw)
@ -667,7 +681,7 @@ class Entry(Widget, tkinter.Entry):
def bbox(self, index): def bbox(self, index):
"""Return a tuple of (x, y, width, height) which describes the """Return a tuple of (x, y, width, height) which describes the
bounding box of the character given by index.""" bounding box of the character given by index."""
return self.tk.call(self._w, "bbox", index) return self._getints(self.tk.call(self._w, "bbox", index))
def identify(self, x, y): def identify(self, x, y):
@ -680,7 +694,7 @@ class Entry(Widget, tkinter.Entry):
"""Force revalidation, independent of the conditions specified """Force revalidation, independent of the conditions specified
by the validate option. Returns False if validation fails, True by the validate option. Returns False if validation fails, True
if it succeeds. Sets or clears the invalid state accordingly.""" if it succeeds. Sets or clears the invalid state accordingly."""
return bool(self.tk.call(self._w, "validate")) return bool(self.tk.getboolean(self.tk.call(self._w, "validate")))
class Combobox(Entry): class Combobox(Entry):
@ -707,6 +721,8 @@ class Combobox(Entry):
element at position newindex in the list of values. Otherwise, element at position newindex in the list of values. Otherwise,
returns the index of the current value in the list of values returns the index of the current value in the list of values
or -1 if the current value does not appear in the list.""" or -1 if the current value does not appear in the list."""
if newindex is None:
return self.tk.getint(self.tk.call(self._w, "current"))
return self.tk.call(self._w, "current", newindex) return self.tk.call(self._w, "current", newindex)
@ -861,7 +877,7 @@ class Notebook(Widget):
def index(self, tab_id): def index(self, tab_id):
"""Returns the numeric index of the tab specified by tab_id, or """Returns the numeric index of the tab specified by tab_id, or
the total number of tabs if tab_id is the string "end".""" the total number of tabs if tab_id is the string "end"."""
return self.tk.call(self._w, "index", tab_id) return self.tk.getint(self.tk.call(self._w, "index", tab_id))
def insert(self, pos, child, **kw): def insert(self, pos, child, **kw):
@ -896,7 +912,7 @@ class Notebook(Widget):
def tabs(self): def tabs(self):
"""Returns a list of windows managed by the notebook.""" """Returns a list of windows managed by the notebook."""
return self.tk.call(self._w, "tabs") or () return self.tk.splitlist(self.tk.call(self._w, "tabs") or ())
def enable_traversal(self): def enable_traversal(self):
@ -979,7 +995,7 @@ class Panedwindow(Widget, tkinter.PanedWindow):
constrained to be between 0 and the total size of the widget. constrained to be between 0 and the total size of the widget.
Returns the new position of sash number index.""" Returns the new position of sash number index."""
return self.tk.call(self._w, "sashpos", index, newpos) return self.tk.getint(self.tk.call(self._w, "sashpos", index, newpos))
PanedWindow = Panedwindow # tkinter name compatibility PanedWindow = Panedwindow # tkinter name compatibility
@ -1179,14 +1195,15 @@ class Treeview(Widget, tkinter.XView, tkinter.YView):
If column is specified, returns the bounding box of that cell. If column is specified, returns the bounding box of that cell.
If the item is not visible (i.e., if it is a descendant of a If the item is not visible (i.e., if it is a descendant of a
closed item or is scrolled offscreen), returns an empty string.""" closed item or is scrolled offscreen), returns an empty string."""
return self.tk.call(self._w, "bbox", item, column) return self._getints(self.tk.call(self._w, "bbox", item, column)) or ''
def get_children(self, item=None): def get_children(self, item=None):
"""Returns a tuple of children belonging to item. """Returns a tuple of children belonging to item.
If item is not specified, returns root children.""" If item is not specified, returns root children."""
return self.tk.call(self._w, "children", item or '') or () return self.tk.splitlist(
self.tk.call(self._w, "children", item or '') or ())
def set_children(self, item, *newchildren): def set_children(self, item, *newchildren):
@ -1227,7 +1244,7 @@ class Treeview(Widget, tkinter.XView, tkinter.YView):
def exists(self, item): def exists(self, item):
"""Returns True if the specified item is present in the tree, """Returns True if the specified item is present in the tree,
False otherwise.""" False otherwise."""
return bool(self.tk.call(self._w, "exists", item)) return bool(self.tk.getboolean(self.tk.call(self._w, "exists", item)))
def focus(self, item=None): def focus(self, item=None):
@ -1309,7 +1326,7 @@ class Treeview(Widget, tkinter.XView, tkinter.YView):
def index(self, item): def index(self, item):
"""Returns the integer index of item within its parent's list """Returns the integer index of item within its parent's list
of children.""" of children."""
return self.tk.call(self._w, "index", item) return self.tk.getint(self.tk.call(self._w, "index", item))
def insert(self, parent, index, iid=None, **kw): def insert(self, parent, index, iid=None, **kw):
@ -1418,7 +1435,7 @@ class Treeview(Widget, tkinter.XView, tkinter.YView):
value of given column in given item to the specified value.""" value of given column in given item to the specified value."""
res = self.tk.call(self._w, "set", item, column, value) res = self.tk.call(self._w, "set", item, column, value)
if column is None and value is None: if column is None and value is None:
return _dict_from_tcltuple(res, False) return _dict_from_tcltuple(self.tk.splitlist(res), False)
else: else:
return res return res
@ -1449,7 +1466,8 @@ class Treeview(Widget, tkinter.XView, tkinter.YView):
all items which have the specified tag. all items which have the specified tag.
* Availability: Tk 8.6""" * Availability: Tk 8.6"""
return self.tk.call(self._w, "tag", "has", tagname, item) return self.tk.getboolean(
self.tk.call(self._w, "tag", "has", tagname, item))
# Extensions # Extensions
@ -1521,7 +1539,8 @@ class LabeledScale(Frame):
self.label.place_configure(x=x, y=y) self.label.place_configure(x=x, y=y)
from_, to = self.scale['from'], self.scale['to'] from_ = _to_number(self.scale['from'])
to = _to_number(self.scale['to'])
if to < from_: if to < from_:
from_, to = to, from_ from_, to = to, from_
newval = self._variable.get() newval = self._variable.get()

View file

@ -13,6 +13,8 @@ Core and Builtins
Library Library
------- -------
- Issue #20072: Fixed multiple errors in tkinter with wantobjects is False.
Tools/Demos Tools/Demos
----------- -----------