Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b49eff2

Browse files
Issue #21402: tkinter.ttk now works when default root window is not set.
1 parent ffc1e6d commit b49eff2

3 files changed

Lines changed: 57 additions & 36 deletions

File tree

Lib/tkinter/test/test_ttk/test_functions.py

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
# -*- encoding: utf-8 -*-
22
import unittest
3+
import tkinter
34
from tkinter import ttk
45

6+
class MockTkApp:
7+
8+
def splitlist(self, arg):
9+
if isinstance(arg, tuple):
10+
return arg
11+
return arg.split(':')
12+
13+
def wantobjects(self):
14+
return True
15+
16+
517
class MockTclObj(object):
618
typename = 'test'
719

@@ -352,20 +364,22 @@ def test_it(sspec, value, res_value, states):
352364

353365

354366
def test_list_from_layouttuple(self):
367+
tk = MockTkApp()
368+
355369
# empty layout tuple
356-
self.assertFalse(ttk._list_from_layouttuple(()))
370+
self.assertFalse(ttk._list_from_layouttuple(tk, ()))
357371

358372
# shortest layout tuple
359-
self.assertEqual(ttk._list_from_layouttuple(('name', )),
373+
self.assertEqual(ttk._list_from_layouttuple(tk, ('name', )),
360374
[('name', {})])
361375

362376
# not so interesting ltuple
363377
sample_ltuple = ('name', '-option', 'value')
364-
self.assertEqual(ttk._list_from_layouttuple(sample_ltuple),
378+
self.assertEqual(ttk._list_from_layouttuple(tk, sample_ltuple),
365379
[('name', {'option': 'value'})])
366380

367381
# empty children
368-
self.assertEqual(ttk._list_from_layouttuple(
382+
self.assertEqual(ttk._list_from_layouttuple(tk,
369383
('something', '-children', ())),
370384
[('something', {'children': []})]
371385
)
@@ -378,7 +392,7 @@ def test_list_from_layouttuple(self):
378392
)
379393
)
380394
)
381-
self.assertEqual(ttk._list_from_layouttuple(ltuple),
395+
self.assertEqual(ttk._list_from_layouttuple(tk, ltuple),
382396
[('name', {'option': 'niceone', 'children':
383397
[('otherone', {'otheropt': 'othervalue', 'children':
384398
[('child', {})]
@@ -387,29 +401,37 @@ def test_list_from_layouttuple(self):
387401
)
388402

389403
# bad tuples
390-
self.assertRaises(ValueError, ttk._list_from_layouttuple,
404+
self.assertRaises(ValueError, ttk._list_from_layouttuple, tk,
391405
('name', 'no_minus'))
392-
self.assertRaises(ValueError, ttk._list_from_layouttuple,
406+
self.assertRaises(ValueError, ttk._list_from_layouttuple, tk,
393407
('name', 'no_minus', 'value'))
394-
self.assertRaises(ValueError, ttk._list_from_layouttuple,
408+
self.assertRaises(ValueError, ttk._list_from_layouttuple, tk,
395409
('something', '-children')) # no children
396-
import tkinter
397-
if not tkinter._default_root or tkinter._default_root.wantobjects():
398-
self.assertRaises(ValueError, ttk._list_from_layouttuple,
399-
('something', '-children', 'value')) # invalid children
410+
self.assertRaises(ValueError, ttk._list_from_layouttuple, tk,
411+
('something', '-children', 'value')) # invalid children
400412

401413

402414
def test_val_or_dict(self):
403-
def func(opt, val=None):
415+
def func(res, opt=None, val=None):
416+
if opt is None:
417+
return res
404418
if val is None:
405419
return "test val"
406420
return (opt, val)
407421

408-
options = {'test': None}
409-
self.assertEqual(ttk._val_or_dict(options, func), "test val")
422+
tk = MockTkApp()
423+
tk.call = func
424+
425+
self.assertEqual(ttk._val_or_dict(tk, {}, '-test:3'),
426+
{'test': '3'})
427+
self.assertEqual(ttk._val_or_dict(tk, {}, ('-test', 3)),
428+
{'test': 3})
429+
430+
self.assertEqual(ttk._val_or_dict(tk, {'test': None}, 'x:y'),
431+
'test val')
410432

411-
options = {'test': 3}
412-
self.assertEqual(ttk._val_or_dict(options, func), options)
433+
self.assertEqual(ttk._val_or_dict(tk, {'test': 3}, 'x:y'),
434+
{'test': 3})
413435

414436

415437
def test_convert_stringval(self):

Lib/tkinter/ttk.py

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ def _list_from_statespec(stuple):
272272
it = iter(nval)
273273
return [_flatten(spec) for spec in zip(it, it)]
274274

275-
def _list_from_layouttuple(ltuple):
275+
def _list_from_layouttuple(tk, ltuple):
276276
"""Construct a list from the tuple returned by ttk::layout, this is
277277
somewhat the reverse of _format_layoutlist."""
278278
res = []
@@ -293,32 +293,29 @@ def _list_from_layouttuple(ltuple):
293293
indx += 2
294294

295295
if opt == 'children':
296-
if (tkinter._default_root and
297-
not tkinter._default_root.wantobjects()):
298-
val = tkinter._default_root.splitlist(val)
299-
val = _list_from_layouttuple(val)
296+
if not tk.wantobjects():
297+
val = tk.splitlist(val)
298+
val = _list_from_layouttuple(tk, val)
300299

301300
opts[opt] = val
302301

303302
return res
304303

305-
def _val_or_dict(options, func, *args):
306-
"""Format options then call func with args and options and return
304+
def _val_or_dict(tk, options, *args):
305+
"""Format options then call Tk command with args and options and return
307306
the appropriate result.
308307
309308
If no option is specified, a dict is returned. If a option is
310309
specified with the None value, the value for that option is returned.
311310
Otherwise, the function just sets the passed options and the caller
312311
shouldn't be expecting a return value anyway."""
313312
options = _format_optdict(options)
314-
res = func(*(args + options))
313+
res = tk.call(*(args + options))
315314

316315
if len(options) % 2: # option specified without a value, return its value
317316
return res
318317

319-
if tkinter._default_root:
320-
res = tkinter._default_root.splitlist(res)
321-
return _dict_from_tcltuple(res)
318+
return _dict_from_tcltuple(tk.splitlist(res))
322319

323320
def _convert_stringval(value):
324321
"""Converts a value to, hopefully, a more appropriate Python object."""
@@ -396,7 +393,7 @@ def configure(self, style, query_opt=None, **kw):
396393
a sequence identifying the value for that option."""
397394
if query_opt is not None:
398395
kw[query_opt] = None
399-
return _val_or_dict(kw, self.tk.call, self._name, "configure", style)
396+
return _val_or_dict(self.tk, kw, self._name, "configure", style)
400397

401398

402399
def map(self, style, query_opt=None, **kw):
@@ -466,7 +463,7 @@ def layout(self, style, layoutspec=None):
466463
lspec = "null" # could be any other word, but this may make sense
467464
# when calling layout(style) later
468465

469-
return _list_from_layouttuple(self.tk.splitlist(
466+
return _list_from_layouttuple(self.tk, self.tk.splitlist(
470467
self.tk.call(self._name, "layout", style, lspec)))
471468

472469

@@ -907,7 +904,7 @@ def tab(self, tab_id, option=None, **kw):
907904
options to the corresponding values."""
908905
if option is not None:
909906
kw[option] = None
910-
return _val_or_dict(kw, self.tk.call, self._w, "tab", tab_id)
907+
return _val_or_dict(self.tk, kw, self._w, "tab", tab_id)
911908

912909

913910
def tabs(self):
@@ -984,7 +981,7 @@ def pane(self, pane, option=None, **kw):
984981
Otherwise, sets the options to the corresponding values."""
985982
if option is not None:
986983
kw[option] = None
987-
return _val_or_dict(kw, self.tk.call, self._w, "pane", pane)
984+
return _val_or_dict(self.tk, kw, self._w, "pane", pane)
988985

989986

990987
def sashpos(self, index, newpos=None):
@@ -1223,7 +1220,7 @@ def column(self, column, option=None, **kw):
12231220
Otherwise, sets the options to the corresponding values."""
12241221
if option is not None:
12251222
kw[option] = None
1226-
return _val_or_dict(kw, self.tk.call, self._w, "column", column)
1223+
return _val_or_dict(self.tk, kw, self._w, "column", column)
12271224

12281225

12291226
def delete(self, *items):
@@ -1282,7 +1279,7 @@ def heading(self, column, option=None, **kw):
12821279
if option is not None:
12831280
kw[option] = None
12841281

1285-
return _val_or_dict(kw, self.tk.call, self._w, 'heading', column)
1282+
return _val_or_dict(self.tk, kw, self._w, 'heading', column)
12861283

12871284

12881285
def identify(self, component, x, y):
@@ -1361,7 +1358,7 @@ def item(self, item, option=None, **kw):
13611358
values as given by kw."""
13621359
if option is not None:
13631360
kw[option] = None
1364-
return _val_or_dict(kw, self.tk.call, self._w, "item", item)
1361+
return _val_or_dict(self.tk, kw, self._w, "item", item)
13651362

13661363

13671364
def move(self, item, parent, index):
@@ -1456,7 +1453,7 @@ def tag_configure(self, tagname, option=None, **kw):
14561453
values for the given tagname."""
14571454
if option is not None:
14581455
kw[option] = None
1459-
return _val_or_dict(kw, self.tk.call, self._w, "tag", "configure",
1456+
return _val_or_dict(self.tk, kw, self._w, "tag", "configure",
14601457
tagname)
14611458

14621459

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Core and Builtins
1818
Library
1919
-------
2020

21+
- Issue #21402: tkinter.ttk now works when default root window is not set.
22+
2123
- Issue #10203: sqlite3.Row now truly supports sequence protocol. In particulr
2224
it supports reverse() and negative indices. Original patch by Claudiu Popa.
2325

0 commit comments

Comments
 (0)