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.
This commit is contained in:
Serhiy Storchaka 2014-08-24 09:10:58 +03:00
commit 66106626ed
15 changed files with 230 additions and 270 deletions

View File

@ -6,7 +6,7 @@ from test import support
support.import_module('_tkinter')
# Make sure tkinter._fix runs to set up the environment
support.import_fresh_module('tkinter')
tkinter = support.import_fresh_module('tkinter')
# Skip test if tk cannot be initialized.
support.requires('gui')
@ -14,20 +14,24 @@ support.requires('gui')
from _tkinter import TclError
from tkinter import ttk
from tkinter.test import runtktests
from tkinter.test.support import get_tk_root
root = None
try:
ttk.Button()
root = tkinter.Tk()
button = ttk.Button(root)
button.destroy()
del button
except TclError as msg:
# assuming ttk is not available
raise unittest.SkipTest("ttk not available: %s" % msg)
finally:
if root is not None:
root.destroy()
del root
def test_main():
try:
support.run_unittest(
*runtktests.get_tests(text=False, packages=['test_ttk']))
finally:
get_tk_root().destroy()
support.run_unittest(
*runtktests.get_tests(text=False, packages=['test_ttk']))
if __name__ == '__main__':
test_main()

View File

@ -562,6 +562,7 @@ class Misc:
self.deletecommand(name)
except TclError:
pass
callit.__name__ = func.__name__
name = self._register(callit)
return self.tk.call('after', ms, name)
def after_idle(self, func, *args):
@ -3314,7 +3315,7 @@ class Image:
master = _default_root
if not master:
raise RuntimeError('Too early to create image')
self.tk = master.tk
self.tk = getattr(master, 'tk', master)
if not name:
Image._last_id += 1
name = "pyimage%r" % (Image._last_id,) # tk itself would use image<x>
@ -3385,20 +3386,20 @@ class PhotoImage(Image):
# XXX copy -from, -to, ...?
def copy(self):
"""Return a new PhotoImage with the same image as this widget."""
destImage = PhotoImage()
destImage = PhotoImage(master=self.tk)
self.tk.call(destImage, 'copy', self.name)
return destImage
def zoom(self,x,y=''):
"""Return a new PhotoImage with the same image as this widget
but zoom it with X and Y."""
destImage = PhotoImage()
destImage = PhotoImage(master=self.tk)
if y=='': y=x
self.tk.call(destImage, 'copy', self.name, '-zoom',x,y)
return destImage
def subsample(self,x,y=''):
"""Return a new PhotoImage based on the same image as this widget
but use only every Xth or Yth pixel."""
destImage = PhotoImage()
destImage = PhotoImage(master=self.tk)
if y=='': y=x
self.tk.call(destImage, 'copy', self.name, '-subsample',x,y)
return destImage

View File

@ -3,30 +3,43 @@ import tkinter
import unittest
from test.support import requires
def get_tk_root():
requires('gui') # raise exception if tk unavailable
try:
root = tkinter._default_root
except AttributeError:
# it is possible to disable default root in Tkinter, although
# I haven't seen people doing it (but apparently someone did it
# here).
root = None
class AbstractTkTest:
if root is None:
# create a new master only if there isn't one already
root = tkinter.Tk()
@classmethod
def setUpClass(cls):
cls._old_support_default_root = tkinter._support_default_root
destroy_default_root()
tkinter.NoDefaultRoot()
cls.root = tkinter.Tk()
cls.wantobjects = cls.root.wantobjects()
# De-maximize main window.
# Some window managers can maximize new windows.
cls.root.wm_state('normal')
try:
cls.root.wm_attributes('-zoomed', False)
except tkinter.TclError:
pass
return root
@classmethod
def tearDownClass(cls):
cls.root.destroy()
cls.root = None
tkinter._default_root = None
tkinter._support_default_root = cls._old_support_default_root
def root_deiconify():
root = get_tk_root()
root.deiconify()
def setUp(self):
self.root.deiconify()
def root_withdraw():
root = get_tk_root()
root.withdraw()
def tearDown(self):
for w in self.root.winfo_children():
w.destroy()
self.root.withdraw()
def destroy_default_root():
if getattr(tkinter, '_default_root', None):
tkinter._default_root.update_idletasks()
tkinter._default_root.destroy()
tkinter._default_root = None
def simulate_mouse_click(widget, x, y):
"""Generate proper events to click at the x, y position (tries to act

View File

@ -2,26 +2,20 @@ import unittest
import tkinter
from tkinter import font
from test.support import requires, run_unittest
import tkinter.test.support as support
from tkinter.test.support import AbstractTkTest
requires('gui')
class FontTest(unittest.TestCase):
def setUp(self):
support.root_deiconify()
def tearDown(self):
support.root_withdraw()
class FontTest(AbstractTkTest, unittest.TestCase):
def test_font_eq(self):
fontname = "TkDefaultFont"
try:
f = font.Font(name=fontname, exists=True)
f = font.Font(root=self.root, name=fontname, exists=True)
except tkinter._tkinter.TclError:
f = font.Font(name=fontname, exists=False)
font1 = font.nametofont(fontname)
font2 = font.nametofont(fontname)
f = font.Font(root=self.root, name=fontname, exists=False)
font1 = font.Font(root=self.root, name=fontname, exists=True)
font2 = font.Font(root=self.root, name=fontname, exists=True)
self.assertIsNot(font1, font2)
self.assertEqual(font1, font2)
self.assertNotEqual(font1, font1.copy())

View File

@ -278,7 +278,7 @@ class PlaceTest(AbstractWidgetTest, unittest.TestCase):
def create2(self):
t = tkinter.Toplevel(self.root, width=300, height=200, bd=0)
t.wm_geometry('+0+0')
t.wm_geometry('300x200+0+0')
f = tkinter.Frame(t, width=154, height=84, bd=2, relief='raised')
f.place_configure(x=48, y=38)
f2 = tkinter.Frame(t, width=30, height=60, bd=2, relief='raised')
@ -479,7 +479,6 @@ class PlaceTest(AbstractWidgetTest, unittest.TestCase):
class GridTest(AbstractWidgetTest, unittest.TestCase):
def tearDown(self):
super().tearDown()
cols, rows = self.root.grid_size()
for i in range(cols + 1):
self.root.grid_columnconfigure(i, weight=0, minsize=0, pad=0, uniform='')
@ -488,10 +487,10 @@ class GridTest(AbstractWidgetTest, unittest.TestCase):
self.root.grid_propagate(1)
if tcl_version >= (8, 5):
self.root.grid_anchor('nw')
super().tearDown()
def test_grid_configure(self):
b = tkinter.Button(self.root)
self.addCleanup(b.destroy)
self.assertEqual(b.grid_info(), {})
b.grid_configure()
self.assertEqual(b.grid_info()['in'], self.root)
@ -578,7 +577,6 @@ class GridTest(AbstractWidgetTest, unittest.TestCase):
def test_grid_configure_row(self):
b = tkinter.Button(self.root)
self.addCleanup(b.destroy)
with self.assertRaisesRegex(TclError, 'bad (row|grid) value "-1": '
'must be a non-negative integer'):
b.grid_configure(row=-1)
@ -795,7 +793,7 @@ class GridTest(AbstractWidgetTest, unittest.TestCase):
self.root.grid_bbox(0, 0, 0, 'x')
with self.assertRaises(TypeError):
self.root.grid_bbox(0, 0, 0, 0, 0)
t = tkinter.Toplevel(self.root)
t = self.root
# de-maximize
t.wm_geometry('1x1+0+0')
t.wm_geometry('')
@ -823,7 +821,7 @@ class GridTest(AbstractWidgetTest, unittest.TestCase):
self.root.grid_location('x', 'y')
with self.assertRaisesRegex(TclError, 'bad screen distance "y"'):
self.root.grid_location('1c', 'y')
t = tkinter.Toplevel(self.root)
t = self.root
# de-maximize
t.wm_geometry('1x1+0+0')
t.wm_geometry('')

View File

@ -1,16 +1,12 @@
import unittest
import tkinter
from tkinter import ttk
from test import support
from tkinter.test.support import requires_tcl
from tkinter.test.support import AbstractTkTest, requires_tcl
support.requires('gui')
class MiscTest(unittest.TestCase):
def setUp(self):
self.root = ttk.setup_master()
class MiscTest(AbstractTkTest, unittest.TestCase):
def test_image_types(self):
image_types = self.root.image_types()
@ -23,15 +19,13 @@ class MiscTest(unittest.TestCase):
self.assertIsInstance(image_names, tuple)
class BitmapImageTest(unittest.TestCase):
class BitmapImageTest(AbstractTkTest, unittest.TestCase):
@classmethod
def setUpClass(cls):
AbstractTkTest.setUpClass.__func__(cls)
cls.testfile = support.findfile('python.xbm', subdir='imghdrdata')
def setUp(self):
self.root = ttk.setup_master()
def test_create_from_file(self):
image = tkinter.BitmapImage('::img::test', master=self.root,
foreground='yellow', background='blue',
@ -107,16 +101,13 @@ class BitmapImageTest(unittest.TestCase):
'-foreground {} {} #000000 yellow')
class PhotoImageTest(unittest.TestCase):
class PhotoImageTest(AbstractTkTest, unittest.TestCase):
@classmethod
def setUpClass(cls):
AbstractTkTest.setUpClass.__func__(cls)
cls.testfile = support.findfile('python.gif', subdir='imghdrdata')
def setUp(self):
self.root = ttk.setup_master()
self.wantobjects = self.root.wantobjects()
def create(self):
return tkinter.PhotoImage('::img::test', master=self.root,
file=self.testfile)

View File

@ -1,14 +1,11 @@
import unittest
import tkinter
from tkinter import ttk
from test import support
from tkinter.test.support import AbstractTkTest
support.requires('gui')
class MiscTest(unittest.TestCase):
def setUp(self):
self.root = ttk.setup_master()
class MiscTest(AbstractTkTest, unittest.TestCase):
def test_repr(self):
t = tkinter.Toplevel(self.root, name='top')

View File

@ -1,19 +1,16 @@
import unittest
import tkinter
from test.support import requires, run_unittest
from tkinter.ttk import setup_master
from tkinter.test.support import AbstractTkTest
requires('gui')
class TextTest(unittest.TestCase):
class TextTest(AbstractTkTest, unittest.TestCase):
def setUp(self):
self.root = setup_master()
super().setUp()
self.text = tkinter.Text(self.root)
def tearDown(self):
self.text.destroy()
def test_debug(self):
text = self.text
olddebug = text.debug()

View File

@ -1,6 +1,6 @@
import unittest
from tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tk
from tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl
class Var(Variable):
@ -16,10 +16,10 @@ class Var(Variable):
class TestBase(unittest.TestCase):
def setUp(self):
self.root = Tk()
self.root = Tcl()
def tearDown(self):
self.root.destroy()
del self.root
class TestVariable(TestBase):
@ -81,7 +81,7 @@ class TestVariable(TestBase):
self.root.setvar(b'var\x00name', "value")
def test_initialize(self):
v = Var()
v = Var(self.root)
self.assertFalse(v.side_effect)
v.set("value")
self.assertTrue(v.side_effect)

View File

@ -66,7 +66,7 @@ class ToplevelTest(AbstractToplevelTest, unittest.TestCase):
'takefocus', 'use', 'visual', 'width',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Toplevel(self.root, **kwargs)
def test_menu(self):
@ -105,7 +105,7 @@ class FrameTest(AbstractToplevelTest, unittest.TestCase):
'relief', 'takefocus', 'visual', 'width',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Frame(self.root, **kwargs)
@ -120,7 +120,7 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
'takefocus', 'text', 'visual', 'width',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.LabelFrame(self.root, **kwargs)
def test_labelanchor(self):
@ -158,7 +158,7 @@ class LabelTest(AbstractLabelTest, unittest.TestCase):
'underline', 'width', 'wraplength',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Label(self.root, **kwargs)
@ -175,7 +175,7 @@ class ButtonTest(AbstractLabelTest, unittest.TestCase):
'state', 'takefocus', 'text', 'textvariable',
'underline', 'width', 'wraplength')
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Button(self.root, **kwargs)
def test_default(self):
@ -199,7 +199,7 @@ class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
'underline', 'variable', 'width', 'wraplength',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Checkbutton(self.root, **kwargs)
@ -227,7 +227,7 @@ class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
'underline', 'value', 'variable', 'width', 'wraplength',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Radiobutton(self.root, **kwargs)
def test_value(self):
@ -250,7 +250,7 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
)
_conv_pixels = staticmethod(pixels_round)
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Menubutton(self.root, **kwargs)
def test_direction(self):
@ -268,7 +268,7 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
'crashes with Cocoa Tk (issue19733)')
def test_image(self):
widget = self.create()
image = tkinter.PhotoImage('image1')
image = tkinter.PhotoImage(master=self.root, name='image1')
self.checkParam(widget, 'image', image, conv=str)
errmsg = 'image "spam" doesn\'t exist'
with self.assertRaises(tkinter.TclError) as cm:
@ -303,7 +303,7 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
class OptionMenuTest(MenubuttonTest, unittest.TestCase):
def _create(self, default='b', values=('a', 'b', 'c'), **kwargs):
def create(self, default='b', values=('a', 'b', 'c'), **kwargs):
return tkinter.OptionMenu(self.root, None, default, *values, **kwargs)
@ -322,7 +322,7 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
'validate', 'validatecommand', 'width', 'xscrollcommand',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Entry(self.root, **kwargs)
def test_disabledbackground(self):
@ -396,7 +396,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
'width', 'wrap', 'xscrollcommand',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Spinbox(self.root, **kwargs)
test_show = None
@ -490,9 +490,9 @@ class TextTest(AbstractWidgetTest, unittest.TestCase):
'xscrollcommand', 'yscrollcommand',
)
if tcl_version < (8, 5):
wantobjects = False
_stringify = True
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Text(self.root, **kwargs)
def test_autoseparators(self):
@ -644,9 +644,9 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase):
)
_conv_pixels = round
wantobjects = False
_stringify = True
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Canvas(self.root, **kwargs)
def test_closeenough(self):
@ -699,7 +699,7 @@ class ListboxTest(AbstractWidgetTest, unittest.TestCase):
'takefocus', 'width', 'xscrollcommand', 'yscrollcommand',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Listbox(self.root, **kwargs)
def test_activestyle(self):
@ -709,7 +709,7 @@ class ListboxTest(AbstractWidgetTest, unittest.TestCase):
def test_listvariable(self):
widget = self.create()
var = tkinter.DoubleVar()
var = tkinter.DoubleVar(self.root)
self.checkVariableParam(widget, 'listvariable', var)
def test_selectmode(self):
@ -831,7 +831,7 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
)
default_orient = 'vertical'
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Scale(self.root, **kwargs)
def test_bigincrement(self):
@ -897,10 +897,10 @@ class ScrollbarTest(AbstractWidgetTest, unittest.TestCase):
'takefocus', 'troughcolor', 'width',
)
_conv_pixels = round
wantobjects = False
_stringify = True
default_orient = 'vertical'
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Scrollbar(self.root, **kwargs)
def test_activerelief(self):
@ -947,7 +947,7 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
)
default_orient = 'horizontal'
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.PanedWindow(self.root, **kwargs)
def test_handlepad(self):
@ -1105,7 +1105,7 @@ class MenuTest(AbstractWidgetTest, unittest.TestCase):
)
_conv_pixels = noconv
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Menu(self.root, **kwargs)
def test_postcommand(self):
@ -1174,7 +1174,7 @@ class MessageTest(AbstractWidgetTest, unittest.TestCase):
)
_conv_pad_pixels = noconv
def _create(self, **kwargs):
def create(self, **kwargs):
return tkinter.Message(self.root, **kwargs)
def test_aspect(self):

View File

@ -2,34 +2,30 @@ import sys
import unittest
import tkinter
from tkinter import ttk
from test.support import requires, run_unittest
import tkinter.test.support as support
from test.support import requires, run_unittest, swap_attr
from tkinter.test.support import AbstractTkTest, destroy_default_root
requires('gui')
class LabeledScaleTest(unittest.TestCase):
def setUp(self):
support.root_deiconify()
class LabeledScaleTest(AbstractTkTest, unittest.TestCase):
def tearDown(self):
support.root_withdraw()
self.root.update_idletasks()
super().tearDown()
def test_widget_destroy(self):
# automatically created variable
x = ttk.LabeledScale()
x = ttk.LabeledScale(self.root)
var = x._variable._name
x.destroy()
self.assertRaises(tkinter.TclError, x.tk.globalgetvar, var)
# manually created variable
myvar = tkinter.DoubleVar()
myvar = tkinter.DoubleVar(self.root)
name = myvar._name
x = ttk.LabeledScale(variable=myvar)
x = ttk.LabeledScale(self.root, variable=myvar)
x.destroy()
if x.tk.wantobjects():
if self.wantobjects:
self.assertEqual(x.tk.globalgetvar(name), myvar.get())
else:
self.assertEqual(float(x.tk.globalgetvar(name)), myvar.get())
@ -37,26 +33,36 @@ class LabeledScaleTest(unittest.TestCase):
self.assertRaises(tkinter.TclError, x.tk.globalgetvar, name)
# checking that the tracing callback is properly removed
myvar = tkinter.IntVar()
myvar = tkinter.IntVar(self.root)
# LabeledScale will start tracing myvar
x = ttk.LabeledScale(variable=myvar)
x = ttk.LabeledScale(self.root, variable=myvar)
x.destroy()
# Unless the tracing callback was removed, creating a new
# LabeledScale with the same var will cause an error now. This
# happens because the variable will be set to (possibly) a new
# value which causes the tracing callback to be called and then
# it tries calling instance attributes not yet defined.
ttk.LabeledScale(variable=myvar)
ttk.LabeledScale(self.root, variable=myvar)
if hasattr(sys, 'last_type'):
self.assertNotEqual(sys.last_type, tkinter.TclError)
def test_initialization_no_master(self):
# no master passing
with swap_attr(tkinter, '_default_root', None), \
swap_attr(tkinter, '_support_default_root', True):
try:
x = ttk.LabeledScale()
self.assertIsNotNone(tkinter._default_root)
self.assertEqual(x.master, tkinter._default_root)
self.assertEqual(x.tk, tkinter._default_root.tk)
x.destroy()
finally:
destroy_default_root()
def test_initialization(self):
# master passing
x = ttk.LabeledScale()
self.assertEqual(x.master, tkinter._default_root)
x.destroy()
master = tkinter.Frame()
master = tkinter.Frame(self.root)
x = ttk.LabeledScale(master)
self.assertEqual(x.master, master)
x.destroy()
@ -64,25 +70,25 @@ class LabeledScaleTest(unittest.TestCase):
# variable initialization/passing
passed_expected = (('0', 0), (0, 0), (10, 10),
(-1, -1), (sys.maxsize + 1, sys.maxsize + 1))
if x.tk.wantobjects():
if self.wantobjects:
passed_expected += ((2.5, 2),)
for pair in passed_expected:
x = ttk.LabeledScale(from_=pair[0])
x = ttk.LabeledScale(self.root, from_=pair[0])
self.assertEqual(x.value, pair[1])
x.destroy()
x = ttk.LabeledScale(from_='2.5')
x = ttk.LabeledScale(self.root, from_='2.5')
self.assertRaises(ValueError, x._variable.get)
x.destroy()
x = ttk.LabeledScale(from_=None)
x = ttk.LabeledScale(self.root, from_=None)
self.assertRaises(ValueError, x._variable.get)
x.destroy()
# variable should have its default value set to the from_ value
myvar = tkinter.DoubleVar(value=20)
x = ttk.LabeledScale(variable=myvar)
myvar = tkinter.DoubleVar(self.root, value=20)
x = ttk.LabeledScale(self.root, variable=myvar)
self.assertEqual(x.value, 0)
x.destroy()
# check that it is really using a DoubleVar
x = ttk.LabeledScale(variable=myvar, from_=0.5)
x = ttk.LabeledScale(self.root, variable=myvar, from_=0.5)
self.assertEqual(x.value, 0.5)
self.assertEqual(x._variable._name, myvar._name)
x.destroy()
@ -91,25 +97,26 @@ class LabeledScaleTest(unittest.TestCase):
def check_positions(scale, scale_pos, label, label_pos):
self.assertEqual(scale.pack_info()['side'], scale_pos)
self.assertEqual(label.place_info()['anchor'], label_pos)
x = ttk.LabeledScale(compound='top')
x = ttk.LabeledScale(self.root, compound='top')
check_positions(x.scale, 'bottom', x.label, 'n')
x.destroy()
x = ttk.LabeledScale(compound='bottom')
x = ttk.LabeledScale(self.root, compound='bottom')
check_positions(x.scale, 'top', x.label, 's')
x.destroy()
x = ttk.LabeledScale(compound='unknown') # invert default positions
# invert default positions
x = ttk.LabeledScale(self.root, compound='unknown')
check_positions(x.scale, 'top', x.label, 's')
x.destroy()
x = ttk.LabeledScale() # take default positions
x = ttk.LabeledScale(self.root) # take default positions
check_positions(x.scale, 'bottom', x.label, 'n')
x.destroy()
# extra, and invalid, kwargs
self.assertRaises(tkinter.TclError, ttk.LabeledScale, a='b')
self.assertRaises(tkinter.TclError, ttk.LabeledScale, master, a='b')
def test_horizontal_range(self):
lscale = ttk.LabeledScale(from_=0, to=10)
lscale = ttk.LabeledScale(self.root, from_=0, to=10)
lscale.pack()
lscale.wait_visibility()
lscale.update()
@ -128,7 +135,7 @@ class LabeledScaleTest(unittest.TestCase):
self.assertNotEqual(prev_xcoord, curr_xcoord)
# the label widget should have been repositioned too
linfo_2 = lscale.label.place_info()
self.assertEqual(lscale.label['text'], 0 if lscale.tk.wantobjects() else '0')
self.assertEqual(lscale.label['text'], 0 if self.wantobjects else '0')
self.assertEqual(curr_xcoord, int(linfo_2['x']))
# change the range back
lscale.scale.configure(from_=0, to=10)
@ -139,7 +146,7 @@ class LabeledScaleTest(unittest.TestCase):
def test_variable_change(self):
x = ttk.LabeledScale()
x = ttk.LabeledScale(self.root)
x.pack()
x.wait_visibility()
x.update()
@ -151,13 +158,13 @@ class LabeledScaleTest(unittest.TestCase):
# at the same time this shouldn't affect test outcome
x.update()
self.assertEqual(x.label['text'],
newval if x.tk.wantobjects() else str(newval))
newval if self.wantobjects else str(newval))
self.assertGreater(x.scale.coords()[0], curr_xcoord)
self.assertEqual(x.scale.coords()[0],
int(x.label.place_info()['x']))
# value outside range
if x.tk.wantobjects():
if self.wantobjects:
conv = lambda x: x
else:
conv = int
@ -171,7 +178,7 @@ class LabeledScaleTest(unittest.TestCase):
def test_resize(self):
x = ttk.LabeledScale()
x = ttk.LabeledScale(self.root)
x.pack(expand=True, fill='both')
x.wait_visibility()
x.update()
@ -190,20 +197,20 @@ class LabeledScaleTest(unittest.TestCase):
x.destroy()
class OptionMenuTest(unittest.TestCase):
class OptionMenuTest(AbstractTkTest, unittest.TestCase):
def setUp(self):
support.root_deiconify()
self.textvar = tkinter.StringVar()
super().setUp()
self.textvar = tkinter.StringVar(self.root)
def tearDown(self):
del self.textvar
support.root_withdraw()
super().tearDown()
def test_widget_destroy(self):
var = tkinter.StringVar()
optmenu = ttk.OptionMenu(None, var)
var = tkinter.StringVar(self.root)
optmenu = ttk.OptionMenu(self.root, var)
name = var._name
optmenu.update_idletasks()
optmenu.destroy()
@ -214,9 +221,9 @@ class OptionMenuTest(unittest.TestCase):
def test_initialization(self):
self.assertRaises(tkinter.TclError,
ttk.OptionMenu, None, self.textvar, invalid='thing')
ttk.OptionMenu, self.root, self.textvar, invalid='thing')
optmenu = ttk.OptionMenu(None, self.textvar, 'b', 'a', 'b')
optmenu = ttk.OptionMenu(self.root, self.textvar, 'b', 'a', 'b')
self.assertEqual(optmenu._variable.get(), 'b')
self.assertTrue(optmenu['menu'])
@ -228,7 +235,7 @@ class OptionMenuTest(unittest.TestCase):
def test_menu(self):
items = ('a', 'b', 'c')
default = 'a'
optmenu = ttk.OptionMenu(None, self.textvar, default, *items)
optmenu = ttk.OptionMenu(self.root, self.textvar, default, *items)
found_default = False
for i in range(len(items)):
value = optmenu['menu'].entrycget(i, 'value')
@ -240,7 +247,7 @@ class OptionMenuTest(unittest.TestCase):
# default shouldn't be in menu if it is not part of values
default = 'd'
optmenu = ttk.OptionMenu(None, self.textvar, default, *items)
optmenu = ttk.OptionMenu(self.root, self.textvar, default, *items)
curr = None
i = 0
while True:
@ -269,7 +276,7 @@ class OptionMenuTest(unittest.TestCase):
def cb_test(item):
self.assertEqual(item, items[1])
success.append(True)
optmenu = ttk.OptionMenu(None, self.textvar, 'a', command=cb_test,
optmenu = ttk.OptionMenu(self.root, self.textvar, 'a', command=cb_test,
*items)
optmenu['menu'].invoke(1)
if not success:

View File

@ -2,15 +2,15 @@ import unittest
import tkinter
from tkinter import ttk
from test.support import requires, run_unittest
import tkinter.test.support as support
from tkinter.test.support import AbstractTkTest
requires('gui')
class StyleTest(unittest.TestCase):
class StyleTest(AbstractTkTest, unittest.TestCase):
def setUp(self):
self.style = ttk.Style()
super().setUp()
self.style = ttk.Style(self.root)
def test_configure(self):
@ -25,7 +25,7 @@ class StyleTest(unittest.TestCase):
style = self.style
style.map('TButton', background=[('active', 'background', 'blue')])
self.assertEqual(style.map('TButton', 'background'),
[('active', 'background', 'blue')] if style.tk.wantobjects() else
[('active', 'background', 'blue')] if self.wantobjects else
[('active background', 'blue')])
self.assertIsInstance(style.map('TButton'), dict)

View File

@ -4,9 +4,9 @@ from tkinter import ttk
from test.support import requires
import sys
import tkinter.test.support as support
from tkinter.test.test_ttk.test_functions import MockTclObj
from tkinter.test.support import tcl_version, get_tk_patchlevel
from tkinter.test.support import (AbstractTkTest, tcl_version, get_tk_patchlevel,
simulate_mouse_click)
from tkinter.test.widget_tests import (add_standard_options, noconv,
AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests,
setUpModule)
@ -53,19 +53,15 @@ class StandardTtkOptionsTests(StandardOptionsTests):
pass
class WidgetTest(unittest.TestCase):
class WidgetTest(AbstractTkTest, unittest.TestCase):
"""Tests methods available in every ttk widget."""
def setUp(self):
support.root_deiconify()
self.widget = ttk.Button(width=0, text="Text")
super().setUp()
self.widget = ttk.Button(self.root, width=0, text="Text")
self.widget.pack()
self.widget.wait_visibility()
def tearDown(self):
self.widget.destroy()
support.root_withdraw()
def test_identify(self):
self.widget.update_idletasks()
@ -128,7 +124,7 @@ class FrameTest(AbstractToplevelTest, unittest.TestCase):
'width',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Frame(self.root, **kwargs)
@ -141,7 +137,7 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
'text', 'underline', 'width',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.LabelFrame(self.root, **kwargs)
def test_labelanchor(self):
@ -161,8 +157,8 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
class AbstractLabelTest(AbstractWidgetTest):
def checkImageParam(self, widget, name):
image = tkinter.PhotoImage('image1')
image2 = tkinter.PhotoImage('image2')
image = tkinter.PhotoImage(master=self.root, name='image1')
image2 = tkinter.PhotoImage(master=self.root, name='image2')
self.checkParam(widget, name, image, expected=('image1',))
self.checkParam(widget, name, 'image1', expected=('image1',))
self.checkParam(widget, name, (image,), expected=('image1',))
@ -199,7 +195,7 @@ class LabelTest(AbstractLabelTest, unittest.TestCase):
)
_conv_pixels = noconv
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Label(self.root, **kwargs)
def test_font(self):
@ -216,7 +212,7 @@ class ButtonTest(AbstractLabelTest, unittest.TestCase):
'underline', 'width',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Button(self.root, **kwargs)
def test_default(self):
@ -225,7 +221,7 @@ class ButtonTest(AbstractLabelTest, unittest.TestCase):
def test_invoke(self):
success = []
btn = ttk.Button(command=lambda: success.append(1))
btn = ttk.Button(self.root, command=lambda: success.append(1))
btn.invoke()
self.assertTrue(success)
@ -241,7 +237,7 @@ class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
'underline', 'variable', 'width',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Checkbutton(self.root, **kwargs)
def test_offvalue(self):
@ -258,7 +254,7 @@ class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
success.append(1)
return "cb test called"
cbtn = ttk.Checkbutton(command=cb_test)
cbtn = ttk.Checkbutton(self.root, command=cb_test)
# the variable automatically created by ttk.Checkbutton is actually
# undefined till we invoke the Checkbutton
self.assertEqual(cbtn.state(), ('alternate', ))
@ -289,15 +285,9 @@ class ComboboxTest(AbstractWidgetTest, unittest.TestCase):
def setUp(self):
super().setUp()
support.root_deiconify()
self.combo = self.create()
def tearDown(self):
self.combo.destroy()
support.root_withdraw()
super().tearDown()
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Combobox(self.root, **kwargs)
def test_height(self):
@ -405,7 +395,7 @@ class ComboboxTest(AbstractWidgetTest, unittest.TestCase):
self.assertRaises(tkinter.TclError, self.combo.current, '')
# testing creating combobox with empty string in values
combo2 = ttk.Combobox(values=[1, 2, ''])
combo2 = ttk.Combobox(self.root, values=[1, 2, ''])
self.assertEqual(combo2['values'],
('1', '2', '') if self.wantobjects else '1 2 {}')
combo2.destroy()
@ -423,15 +413,9 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
def setUp(self):
super().setUp()
support.root_deiconify()
self.entry = self.create()
def tearDown(self):
self.entry.destroy()
support.root_withdraw()
super().tearDown()
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Entry(self.root, **kwargs)
def test_invalidcommand(self):
@ -558,15 +542,9 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
def setUp(self):
super().setUp()
support.root_deiconify()
self.paned = self.create()
def tearDown(self):
self.paned.destroy()
support.root_withdraw()
super().tearDown()
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.PanedWindow(self.root, **kwargs)
def test_orient(self):
@ -588,13 +566,13 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
label.destroy()
child.destroy()
# another attempt
label = ttk.Label()
label = ttk.Label(self.root)
child = ttk.Label(label)
self.assertRaises(tkinter.TclError, self.paned.add, child)
child.destroy()
label.destroy()
good_child = ttk.Label()
good_child = ttk.Label(self.root)
self.paned.add(good_child)
# re-adding a child is not accepted
self.assertRaises(tkinter.TclError, self.paned.add, good_child)
@ -612,7 +590,7 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
self.assertRaises(tkinter.TclError, self.paned.forget, None)
self.assertRaises(tkinter.TclError, self.paned.forget, 0)
self.paned.add(ttk.Label())
self.paned.add(ttk.Label(self.root))
self.paned.forget(0)
self.assertRaises(tkinter.TclError, self.paned.forget, 0)
@ -622,9 +600,9 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
self.assertRaises(tkinter.TclError, self.paned.insert, 0, None)
self.assertRaises(tkinter.TclError, self.paned.insert, 0, 0)
child = ttk.Label()
child2 = ttk.Label()
child3 = ttk.Label()
child = ttk.Label(self.root)
child2 = ttk.Label(self.root)
child3 = ttk.Label(self.root)
self.assertRaises(tkinter.TclError, self.paned.insert, 0, child)
@ -655,7 +633,7 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
def test_pane(self):
self.assertRaises(tkinter.TclError, self.paned.pane, 0)
child = ttk.Label()
child = ttk.Label(self.root)
self.paned.add(child)
self.assertIsInstance(self.paned.pane(0), dict)
self.assertEqual(self.paned.pane(0, weight=None),
@ -700,7 +678,7 @@ class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
'underline', 'value', 'variable', 'width',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Radiobutton(self.root, **kwargs)
def test_value(self):
@ -713,9 +691,11 @@ class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
success.append(1)
return "cb test called"
myvar = tkinter.IntVar()
cbtn = ttk.Radiobutton(command=cb_test, variable=myvar, value=0)
cbtn2 = ttk.Radiobutton(command=cb_test, variable=myvar, value=1)
myvar = tkinter.IntVar(self.root)
cbtn = ttk.Radiobutton(self.root, command=cb_test,
variable=myvar, value=0)
cbtn2 = ttk.Radiobutton(self.root, command=cb_test,
variable=myvar, value=1)
if self.wantobjects:
conv = lambda x: x
@ -748,7 +728,7 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
'underline', 'width',
)
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Menubutton(self.root, **kwargs)
def test_direction(self):
@ -774,17 +754,11 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
def setUp(self):
super().setUp()
support.root_deiconify()
self.scale = self.create()
self.scale.pack()
self.scale.update()
def tearDown(self):
self.scale.destroy()
support.root_withdraw()
super().tearDown()
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Scale(self.root, **kwargs)
def test_from(self):
@ -856,7 +830,7 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
self.assertEqual(conv(self.scale.get()), min)
# changing directly the variable doesn't impose this limitation tho
var = tkinter.DoubleVar()
var = tkinter.DoubleVar(self.root)
self.scale['variable'] = var
var.set(max + 5)
self.assertEqual(conv(self.scale.get()), var.get())
@ -886,7 +860,7 @@ class ProgressbarTest(AbstractWidgetTest, unittest.TestCase):
_conv_pixels = noconv
default_orient = 'horizontal'
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Progressbar(self.root, **kwargs)
def test_length(self):
@ -920,7 +894,7 @@ class ScrollbarTest(AbstractWidgetTest, unittest.TestCase):
)
default_orient = 'vertical'
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Scrollbar(self.root, **kwargs)
@ -932,21 +906,13 @@ class NotebookTest(AbstractWidgetTest, unittest.TestCase):
def setUp(self):
super().setUp()
support.root_deiconify()
self.nb = self.create(padding=0)
self.child1 = ttk.Label()
self.child2 = ttk.Label()
self.child1 = ttk.Label(self.root)
self.child2 = ttk.Label(self.root)
self.nb.add(self.child1, text='a')
self.nb.add(self.child2, text='b')
def tearDown(self):
self.child1.destroy()
self.child2.destroy()
self.nb.destroy()
support.root_withdraw()
super().tearDown()
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Notebook(self.root, **kwargs)
def test_tab_identifiers(self):
@ -985,7 +951,7 @@ class NotebookTest(AbstractWidgetTest, unittest.TestCase):
self.assertRaises(tkinter.TclError, self.nb.hide, 'hi')
self.assertRaises(tkinter.TclError, self.nb.hide, None)
self.assertRaises(tkinter.TclError, self.nb.add, None)
self.assertRaises(tkinter.TclError, self.nb.add, ttk.Label(),
self.assertRaises(tkinter.TclError, self.nb.add, ttk.Label(self.root),
unknown='option')
tabs = self.nb.tabs()
@ -993,7 +959,7 @@ class NotebookTest(AbstractWidgetTest, unittest.TestCase):
self.nb.add(self.child1)
self.assertEqual(self.nb.tabs(), tabs)
child = ttk.Label()
child = ttk.Label(self.root)
self.nb.add(child, text='c')
tabs = self.nb.tabs()
@ -1051,7 +1017,7 @@ class NotebookTest(AbstractWidgetTest, unittest.TestCase):
self.assertRaises(tkinter.TclError, self.nb.insert, -1, tabs[0])
# new tab
child3 = ttk.Label()
child3 = ttk.Label(self.root)
self.nb.insert(1, child3)
self.assertEqual(self.nb.tabs(), (tabs[0], str(child3), tabs[1]))
self.nb.forget(child3)
@ -1117,7 +1083,7 @@ class NotebookTest(AbstractWidgetTest, unittest.TestCase):
self.nb.select(0)
support.simulate_mouse_click(self.nb, 5, 5)
simulate_mouse_click(self.nb, 5, 5)
self.nb.focus_force()
self.nb.event_generate('<Control-Tab>')
self.assertEqual(self.nb.select(), str(self.child2))
@ -1131,7 +1097,7 @@ class NotebookTest(AbstractWidgetTest, unittest.TestCase):
self.nb.tab(self.child1, text='a', underline=0)
self.nb.enable_traversal()
self.nb.focus_force()
support.simulate_mouse_click(self.nb, 5, 5)
simulate_mouse_click(self.nb, 5, 5)
if sys.platform == 'darwin':
self.nb.event_generate('<Option-a>')
else:
@ -1149,15 +1115,9 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
def setUp(self):
super().setUp()
support.root_deiconify()
self.tv = self.create(padding=0)
def tearDown(self):
self.tv.destroy()
support.root_withdraw()
super().tearDown()
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Treeview(self.root, **kwargs)
def test_columns(self):
@ -1393,7 +1353,7 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
def test_heading_callback(self):
def simulate_heading_click(x, y):
support.simulate_mouse_click(self.tv, x, y)
simulate_mouse_click(self.tv, x, y)
self.tv.update()
success = [] # no success for now
@ -1582,7 +1542,7 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
self.assertEqual(len(pos_y), 2) # item1 and item2 y pos
for y in pos_y:
support.simulate_mouse_click(self.tv, 0, y)
simulate_mouse_click(self.tv, 0, y)
# by now there should be 4 things in the events list, since each
# item had a bind for two events that were simulated above
@ -1612,7 +1572,7 @@ class SeparatorTest(AbstractWidgetTest, unittest.TestCase):
)
default_orient = 'horizontal'
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Separator(self.root, **kwargs)
@ -1623,7 +1583,7 @@ class SizegripTest(AbstractWidgetTest, unittest.TestCase):
# 'state'?
)
def _create(self, **kwargs):
def create(self, **kwargs):
return ttk.Sizegrip(self.root, **kwargs)
tests_gui = (

View File

@ -3,9 +3,9 @@
import unittest
import sys
import tkinter
from tkinter.ttk import setup_master, Scale
from tkinter.test.support import (tcl_version, requires_tcl, get_tk_patchlevel,
pixels_conv, tcl_obj_eq)
from tkinter.ttk import Scale
from tkinter.test.support import (AbstractTkTest, tcl_version, requires_tcl,
get_tk_patchlevel, pixels_conv, tcl_obj_eq)
import test.support
@ -22,33 +22,26 @@ if get_tk_patchlevel()[:3] == (8, 5, 11):
_sentinel = object()
class AbstractWidgetTest:
class AbstractWidgetTest(AbstractTkTest):
_conv_pixels = staticmethod(pixels_round)
_conv_pad_pixels = None
wantobjects = True
_stringify = False
def setUp(self):
self.root = setup_master()
self.scaling = float(self.root.call('tk', 'scaling'))
if not self.root.wantobjects():
self.wantobjects = False
def tearDown(self):
for w in self.root.winfo_children():
w.destroy()
@property
def scaling(self):
try:
return self._scaling
except AttributeError:
self._scaling = float(self.root.call('tk', 'scaling'))
return self._scaling
def _str(self, value):
if self.wantobjects and tcl_version >= (8, 6):
if not self._stringify and self.wantobjects and tcl_version >= (8, 6):
return value
if isinstance(value, tuple):
return ' '.join(map(self._str, value))
return str(value)
def create(self, **kwargs):
widget = self._create(**kwargs)
self.addCleanup(widget.destroy)
return widget
def assertEqual2(self, actual, expected, msg=None, eq=object.__eq__):
if eq(actual, expected):
return
@ -61,7 +54,7 @@ class AbstractWidgetTest:
expected = value
if conv:
expected = conv(expected)
if not self.wantobjects:
if self._stringify or not self.wantobjects:
if isinstance(expected, tuple):
expected = tkinter._join(expected)
else:
@ -193,7 +186,7 @@ class AbstractWidgetTest:
errmsg=errmsg)
def checkImageParam(self, widget, name):
image = tkinter.PhotoImage('image1')
image = tkinter.PhotoImage(master=self.root, name='image1')
self.checkParam(widget, name, image, conv=str)
self.checkInvalidParam(widget, name, 'spam',
errmsg='image "spam" doesn\'t exist')
@ -414,7 +407,7 @@ class StandardOptionsTests:
def test_textvariable(self):
widget = self.create()
var = tkinter.StringVar()
var = tkinter.StringVar(self.root)
self.checkVariableParam(widget, 'textvariable', var)
def test_troughcolor(self):
@ -475,7 +468,7 @@ class StandardOptionsTests:
def test_variable(self):
widget = self.create()
var = tkinter.DoubleVar()
var = tkinter.DoubleVar(self.root)
self.checkVariableParam(widget, 'variable', var)

View File

@ -124,6 +124,8 @@ Core and Builtins
Library
-------
- Issue #22236: Fixed Tkinter images copying operations in NoDefaultRoot mode.
- Issue #2527: Add a *globals* argument to timeit functions, in order to
override the globals namespace in which the timed code is executed.
Patch by Ben Roberts.
@ -418,6 +420,9 @@ Library
- Issue #21525: Most Tkinter methods which accepted tuples now accept lists too.
- Issue #22236: Tkinter tests now don't reuse default root window. New root
window is created for every test class.
- Issue #10744: Fix PEP 3118 format strings on ctypes objects with a nontrivial
shape.