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:27:42 +02:00
parent 0455c3fd28
commit a21acb5d95
7 changed files with 153 additions and 71 deletions

View file

@ -1459,11 +1459,11 @@ def event_info(self, virtual=None):
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 @@ def wm_colormapwindows(self, *wlist):
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
@ -3472,8 +3476,11 @@ def __init__(self, name=None, cnf={}, master=None, **kw):
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):
@ -3842,7 +3849,7 @@ def paneconfigure(self, tagOrId, cnf=None, **kw):
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 @@ def test_widget_destroy(self):
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 @@ def test_initialization(self):
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 @@ def test_horizontal_range(self):
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 @@ def test_variable_change(self):
# 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 @@ def test_list_from_layouttuple(self):
('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 @@ def test_map(self):
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 @@ def check_get_current(getval, currval):
# 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 @@ def check_get_current(getval, currval):
# 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 @@ def test_pane(self):
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 @@ def cb_test():
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 @@ def test_custom_event(self):
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 @@ def test_get(self):
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 @@ def test_bbox(self):
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 @@ def test_column(self):
# 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 @@ def test_insert_item(self):
# 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 @@ def test_insert_item(self):
# 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 @@ def test_set(self):
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 @@ def map(self, style, query_opt=None, **kw):
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 @@ def layout(self, style, layoutspec=None):
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 @@ def element_create(self, elementname, etype, *args, **kw):
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 @@ def theme_settings(self, themename, settings):
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 @@ def instate(self, statespec, callback=None, *args, **kw):
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 @@ def __init__(self, master=None, widget=None, **kw):
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 @@ def validate(self):
"""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 @@ def current(self, newindex=None):
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 @@ def identify(self, x, y):
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 @@ def tab(self, tab_id, option=None, **kw):
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 @@ def sashpos(self, index, newpos=None):
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 @@ def bbox(self, item, column=None):
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 @@ def detach(self, *items):
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 @@ def identify_element(self, x, y):
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 @@ def set(self, item, column=None, value=None):
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 @@ def tag_has(self, tagname, item=None):
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 @@ def adjust_label():
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

@ -31,6 +31,8 @@ Core and Builtins
Library Library
------- -------
- Issue #20072: Fixed multiple errors in tkinter with wantobjects is False.
- Issue #20108: Avoid parameter name clash in inspect.getcallargs(). - Issue #20108: Avoid parameter name clash in inspect.getcallargs().
- Issue #12692: Backport the fix for ResourceWarning in test_urllib2net. This - Issue #12692: Backport the fix for ResourceWarning in test_urllib2net. This