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

Skip to content

Commit d00aff2

Browse files
Issue #22236: Tkinter tests now don't reuse default root window. New root
window is created for every test class. Fixed Tkinter images copying operations in NoDefaultRoot mode. Tcl command names generated for "after" callbacks now contains a name of original function.
1 parent ee55826 commit d00aff2

15 files changed

Lines changed: 231 additions & 271 deletions

Lib/test/test_ttk_guionly.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,32 @@
66
support.import_module('_tkinter')
77

88
# Make sure tkinter._fix runs to set up the environment
9-
support.import_fresh_module('tkinter')
9+
tkinter = support.import_fresh_module('tkinter')
1010

1111
# Skip test if tk cannot be initialized.
1212
support.requires('gui')
1313

1414
from _tkinter import TclError
1515
from tkinter import ttk
1616
from tkinter.test import runtktests
17-
from tkinter.test.support import get_tk_root
1817

18+
root = None
1919
try:
20-
ttk.Button()
20+
root = tkinter.Tk()
21+
button = ttk.Button(root)
22+
button.destroy()
23+
del button
2124
except TclError as msg:
2225
# assuming ttk is not available
2326
raise unittest.SkipTest("ttk not available: %s" % msg)
27+
finally:
28+
if root is not None:
29+
root.destroy()
30+
del root
2431

2532
def test_main():
26-
try:
27-
support.run_unittest(
28-
*runtktests.get_tests(text=False, packages=['test_ttk']))
29-
finally:
30-
get_tk_root().destroy()
33+
support.run_unittest(
34+
*runtktests.get_tests(text=False, packages=['test_ttk']))
3135

3236
if __name__ == '__main__':
3337
test_main()

Lib/tkinter/__init__.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ def callit():
562562
self.deletecommand(name)
563563
except TclError:
564564
pass
565+
callit.__name__ = func.__name__
565566
name = self._register(callit)
566567
return self.tk.call('after', ms, name)
567568
def after_idle(self, func, *args):
@@ -3351,7 +3352,7 @@ def __init__(self, imgtype, name=None, cnf={}, master=None, **kw):
33513352
master = _default_root
33523353
if not master:
33533354
raise RuntimeError('Too early to create image')
3354-
self.tk = master.tk
3355+
self.tk = getattr(master, 'tk', master)
33553356
if not name:
33563357
Image._last_id += 1
33573358
name = "pyimage%r" % (Image._last_id,) # tk itself would use image<x>
@@ -3422,20 +3423,20 @@ def __getitem__(self, key):
34223423
# XXX copy -from, -to, ...?
34233424
def copy(self):
34243425
"""Return a new PhotoImage with the same image as this widget."""
3425-
destImage = PhotoImage()
3426+
destImage = PhotoImage(master=self.tk)
34263427
self.tk.call(destImage, 'copy', self.name)
34273428
return destImage
34283429
def zoom(self,x,y=''):
34293430
"""Return a new PhotoImage with the same image as this widget
34303431
but zoom it with X and Y."""
3431-
destImage = PhotoImage()
3432+
destImage = PhotoImage(master=self.tk)
34323433
if y=='': y=x
34333434
self.tk.call(destImage, 'copy', self.name, '-zoom',x,y)
34343435
return destImage
34353436
def subsample(self,x,y=''):
34363437
"""Return a new PhotoImage based on the same image as this widget
34373438
but use only every Xth or Yth pixel."""
3438-
destImage = PhotoImage()
3439+
destImage = PhotoImage(master=self.tk)
34393440
if y=='': y=x
34403441
self.tk.call(destImage, 'copy', self.name, '-subsample',x,y)
34413442
return destImage

Lib/tkinter/test/support.py

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,43 @@
33
import unittest
44
from test.support import requires
55

6-
def get_tk_root():
7-
requires('gui') # raise exception if tk unavailable
8-
try:
9-
root = tkinter._default_root
10-
except AttributeError:
11-
# it is possible to disable default root in Tkinter, although
12-
# I haven't seen people doing it (but apparently someone did it
13-
# here).
14-
root = None
6+
class AbstractTkTest:
157

16-
if root is None:
17-
# create a new master only if there isn't one already
18-
root = tkinter.Tk()
8+
@classmethod
9+
def setUpClass(cls):
10+
cls._old_support_default_root = tkinter._support_default_root
11+
destroy_default_root()
12+
tkinter.NoDefaultRoot()
13+
cls.root = tkinter.Tk()
14+
cls.wantobjects = cls.root.wantobjects()
15+
# De-maximize main window.
16+
# Some window managers can maximize new windows.
17+
cls.root.wm_state('normal')
18+
try:
19+
cls.root.wm_attributes('-zoomed', False)
20+
except tkinter.TclError:
21+
pass
1922

20-
return root
23+
@classmethod
24+
def tearDownClass(cls):
25+
cls.root.destroy()
26+
cls.root = None
27+
tkinter._default_root = None
28+
tkinter._support_default_root = cls._old_support_default_root
2129

22-
def root_deiconify():
23-
root = get_tk_root()
24-
root.deiconify()
30+
def setUp(self):
31+
self.root.deiconify()
2532

26-
def root_withdraw():
27-
root = get_tk_root()
28-
root.withdraw()
33+
def tearDown(self):
34+
for w in self.root.winfo_children():
35+
w.destroy()
36+
self.root.withdraw()
2937

38+
def destroy_default_root():
39+
if getattr(tkinter, '_default_root', None):
40+
tkinter._default_root.update_idletasks()
41+
tkinter._default_root.destroy()
42+
tkinter._default_root = None
3043

3144
def simulate_mouse_click(widget, x, y):
3245
"""Generate proper events to click at the x, y position (tries to act

Lib/tkinter/test/test_tkinter/test_font.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,20 @@
22
import tkinter
33
from tkinter import font
44
from test.support import requires, run_unittest
5-
import tkinter.test.support as support
5+
from tkinter.test.support import AbstractTkTest
66

77
requires('gui')
88

9-
class FontTest(unittest.TestCase):
10-
11-
def setUp(self):
12-
support.root_deiconify()
13-
14-
def tearDown(self):
15-
support.root_withdraw()
9+
class FontTest(AbstractTkTest, unittest.TestCase):
1610

1711
def test_font_eq(self):
1812
fontname = "TkDefaultFont"
1913
try:
20-
f = font.Font(name=fontname, exists=True)
14+
f = font.Font(root=self.root, name=fontname, exists=True)
2115
except tkinter._tkinter.TclError:
22-
f = font.Font(name=fontname, exists=False)
23-
font1 = font.nametofont(fontname)
24-
font2 = font.nametofont(fontname)
16+
f = font.Font(root=self.root, name=fontname, exists=False)
17+
font1 = font.Font(root=self.root, name=fontname, exists=True)
18+
font2 = font.Font(root=self.root, name=fontname, exists=True)
2519
self.assertIsNot(font1, font2)
2620
self.assertEqual(font1, font2)
2721
self.assertNotEqual(font1, font1.copy())

Lib/tkinter/test/test_tkinter/test_geometry_managers.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ class PlaceTest(AbstractWidgetTest, unittest.TestCase):
278278

279279
def create2(self):
280280
t = tkinter.Toplevel(self.root, width=300, height=200, bd=0)
281-
t.wm_geometry('+0+0')
281+
t.wm_geometry('300x200+0+0')
282282
f = tkinter.Frame(t, width=154, height=84, bd=2, relief='raised')
283283
f.place_configure(x=48, y=38)
284284
f2 = tkinter.Frame(t, width=30, height=60, bd=2, relief='raised')
@@ -479,7 +479,6 @@ def test_place_slaves(self):
479479
class GridTest(AbstractWidgetTest, unittest.TestCase):
480480

481481
def tearDown(self):
482-
super().tearDown()
483482
cols, rows = self.root.grid_size()
484483
for i in range(cols + 1):
485484
self.root.grid_columnconfigure(i, weight=0, minsize=0, pad=0, uniform='')
@@ -488,10 +487,10 @@ def tearDown(self):
488487
self.root.grid_propagate(1)
489488
if tcl_version >= (8, 5):
490489
self.root.grid_anchor('nw')
490+
super().tearDown()
491491

492492
def test_grid_configure(self):
493493
b = tkinter.Button(self.root)
494-
self.addCleanup(b.destroy)
495494
self.assertEqual(b.grid_info(), {})
496495
b.grid_configure()
497496
self.assertEqual(b.grid_info()['in'], self.root)
@@ -578,7 +577,6 @@ def test_grid_configure_pady(self):
578577

579578
def test_grid_configure_row(self):
580579
b = tkinter.Button(self.root)
581-
self.addCleanup(b.destroy)
582580
with self.assertRaisesRegex(TclError, 'bad (row|grid) value "-1": '
583581
'must be a non-negative integer'):
584582
b.grid_configure(row=-1)
@@ -795,7 +793,7 @@ def test_grid_bbox(self):
795793
self.root.grid_bbox(0, 0, 0, 'x')
796794
with self.assertRaises(TypeError):
797795
self.root.grid_bbox(0, 0, 0, 0, 0)
798-
t = tkinter.Toplevel(self.root)
796+
t = self.root
799797
# de-maximize
800798
t.wm_geometry('1x1+0+0')
801799
t.wm_geometry('')
@@ -823,7 +821,7 @@ def test_grid_location(self):
823821
self.root.grid_location('x', 'y')
824822
with self.assertRaisesRegex(TclError, 'bad screen distance "y"'):
825823
self.root.grid_location('1c', 'y')
826-
t = tkinter.Toplevel(self.root)
824+
t = self.root
827825
# de-maximize
828826
t.wm_geometry('1x1+0+0')
829827
t.wm_geometry('')

Lib/tkinter/test/test_tkinter/test_images.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
import unittest
22
import tkinter
3-
from tkinter import ttk
43
from test import support
5-
from tkinter.test.support import requires_tcl
4+
from tkinter.test.support import AbstractTkTest, requires_tcl
65

76
support.requires('gui')
87

98

10-
class MiscTest(unittest.TestCase):
11-
12-
def setUp(self):
13-
self.root = ttk.setup_master()
9+
class MiscTest(AbstractTkTest, unittest.TestCase):
1410

1511
def test_image_types(self):
1612
image_types = self.root.image_types()
@@ -23,15 +19,13 @@ def test_image_names(self):
2319
self.assertIsInstance(image_names, tuple)
2420

2521

26-
class BitmapImageTest(unittest.TestCase):
22+
class BitmapImageTest(AbstractTkTest, unittest.TestCase):
2723

2824
@classmethod
2925
def setUpClass(cls):
26+
AbstractTkTest.setUpClass.__func__(cls)
3027
cls.testfile = support.findfile('python.xbm', subdir='imghdrdata')
3128

32-
def setUp(self):
33-
self.root = ttk.setup_master()
34-
3529
def test_create_from_file(self):
3630
image = tkinter.BitmapImage('::img::test', master=self.root,
3731
foreground='yellow', background='blue',
@@ -107,16 +101,13 @@ def test_configure_foreground(self):
107101
'-foreground {} {} #000000 yellow')
108102

109103

110-
class PhotoImageTest(unittest.TestCase):
104+
class PhotoImageTest(AbstractTkTest, unittest.TestCase):
111105

112106
@classmethod
113107
def setUpClass(cls):
108+
AbstractTkTest.setUpClass.__func__(cls)
114109
cls.testfile = support.findfile('python.gif', subdir='imghdrdata')
115110

116-
def setUp(self):
117-
self.root = ttk.setup_master()
118-
self.wantobjects = self.root.wantobjects()
119-
120111
def create(self):
121112
return tkinter.PhotoImage('::img::test', master=self.root,
122113
file=self.testfile)

Lib/tkinter/test/test_tkinter/test_misc.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import unittest
22
import tkinter
3-
from tkinter import ttk
43
from test import support
4+
from tkinter.test.support import AbstractTkTest
55

66
support.requires('gui')
77

8-
class MiscTest(unittest.TestCase):
9-
10-
def setUp(self):
11-
self.root = ttk.setup_master()
8+
class MiscTest(AbstractTkTest, unittest.TestCase):
129

1310
def test_tk_setPalette(self):
1411
root = self.root

Lib/tkinter/test/test_tkinter/test_text.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
import unittest
22
import tkinter
33
from test.support import requires, run_unittest
4-
from tkinter.ttk import setup_master
4+
from tkinter.test.support import AbstractTkTest
55

66
requires('gui')
77

8-
class TextTest(unittest.TestCase):
8+
class TextTest(AbstractTkTest, unittest.TestCase):
99

1010
def setUp(self):
11-
self.root = setup_master()
11+
super().setUp()
1212
self.text = tkinter.Text(self.root)
1313

14-
def tearDown(self):
15-
self.text.destroy()
16-
1714
def test_debug(self):
1815
text = self.text
1916
olddebug = text.debug()

Lib/tkinter/test/test_tkinter/test_variables.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import unittest
22

3-
from tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tk
3+
from tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl
44

55

66
class Var(Variable):
@@ -16,10 +16,10 @@ def set(self, value):
1616
class TestBase(unittest.TestCase):
1717

1818
def setUp(self):
19-
self.root = Tk()
19+
self.root = Tcl()
2020

2121
def tearDown(self):
22-
self.root.destroy()
22+
del self.root
2323

2424

2525
class TestVariable(TestBase):
@@ -81,7 +81,7 @@ def test_null_in_name(self):
8181
self.root.setvar(b'var\x00name', "value")
8282

8383
def test_initialize(self):
84-
v = Var()
84+
v = Var(self.root)
8585
self.assertFalse(v.side_effect)
8686
v.set("value")
8787
self.assertTrue(v.side_effect)

0 commit comments

Comments
 (0)