changeset: 92222:dd1dffe6f0d2 branch: 3.4 parent: 92219:4a6b71d8575e user: Serhiy Storchaka date: Sun Aug 24 09:07:47 2014 +0300 files: Lib/test/test_ttk_guionly.py Lib/tkinter/__init__.py Lib/tkinter/test/support.py Lib/tkinter/test/test_tkinter/test_font.py Lib/tkinter/test/test_tkinter/test_geometry_managers.py Lib/tkinter/test/test_tkinter/test_images.py Lib/tkinter/test/test_tkinter/test_misc.py Lib/tkinter/test/test_tkinter/test_text.py Lib/tkinter/test/test_tkinter/test_variables.py Lib/tkinter/test/test_tkinter/test_widgets.py Lib/tkinter/test/test_ttk/test_extensions.py Lib/tkinter/test/test_ttk/test_style.py Lib/tkinter/test/test_ttk/test_widgets.py Lib/tkinter/test/widget_tests.py Misc/NEWS description: 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. diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/test/test_ttk_guionly.py --- a/Lib/test/test_ttk_guionly.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/test/test_ttk_guionly.py Sun Aug 24 09:07:47 2014 +0300 @@ -6,7 +6,7 @@ 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 @@ 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() diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/__init__.py --- a/Lib/tkinter/__init__.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/__init__.py Sun Aug 24 09:07:47 2014 +0300 @@ -562,6 +562,7 @@ 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): @@ -3351,7 +3352,7 @@ 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 @@ -3422,20 +3423,20 @@ # 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 diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/support.py --- a/Lib/tkinter/test/support.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/support.py Sun Aug 24 09:07:47 2014 +0300 @@ -3,30 +3,43 @@ 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: + + @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 - if root is None: - # create a new master only if there isn't one already - root = tkinter.Tk() + @classmethod + def tearDownClass(cls): + cls.root.destroy() + cls.root = None + tkinter._default_root = None + tkinter._support_default_root = cls._old_support_default_root - return root + def setUp(self): + self.root.deiconify() -def root_deiconify(): - root = get_tk_root() - root.deiconify() + def tearDown(self): + for w in self.root.winfo_children(): + w.destroy() + self.root.withdraw() -def root_withdraw(): - root = get_tk_root() - 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 diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/test_tkinter/test_font.py --- a/Lib/tkinter/test/test_tkinter/test_font.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/test_tkinter/test_font.py Sun Aug 24 09:07:47 2014 +0300 @@ -2,26 +2,20 @@ 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()) diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/test_tkinter/test_geometry_managers.py --- a/Lib/tkinter/test/test_tkinter/test_geometry_managers.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/test_tkinter/test_geometry_managers.py Sun Aug 24 09:07:47 2014 +0300 @@ -278,7 +278,7 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ 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('') diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/test_tkinter/test_images.py --- a/Lib/tkinter/test/test_tkinter/test_images.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/test_tkinter/test_images.py Sun Aug 24 09:07:47 2014 +0300 @@ -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 @@ 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 @@ '-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) diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/test_tkinter/test_misc.py --- a/Lib/tkinter/test/test_tkinter/test_misc.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/test_tkinter/test_misc.py Sun Aug 24 09:07:47 2014 +0300 @@ -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_tk_setPalette(self): root = self.root diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/test_tkinter/test_text.py --- a/Lib/tkinter/test/test_tkinter/test_text.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/test_tkinter/test_text.py Sun Aug 24 09:07:47 2014 +0300 @@ -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() diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/test_tkinter/test_variables.py --- a/Lib/tkinter/test/test_tkinter/test_variables.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/test_tkinter/test_variables.py Sun Aug 24 09:07:47 2014 +0300 @@ -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 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 @@ 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) diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/test_tkinter/test_widgets.py --- a/Lib/tkinter/test/test_tkinter/test_widgets.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/test_tkinter/test_widgets.py Sun Aug 24 09:07:47 2014 +0300 @@ -66,7 +66,7 @@ '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 @@ 'relief', 'takefocus', 'visual', 'width', ) - def _create(self, **kwargs): + def create(self, **kwargs): return tkinter.Frame(self.root, **kwargs) @@ -120,7 +120,7 @@ '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 @@ 'underline', 'width', 'wraplength', ) - def _create(self, **kwargs): + def create(self, **kwargs): return tkinter.Label(self.root, **kwargs) @@ -175,7 +175,7 @@ '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 @@ 'underline', 'variable', 'width', 'wraplength', ) - def _create(self, **kwargs): + def create(self, **kwargs): return tkinter.Checkbutton(self.root, **kwargs) @@ -227,7 +227,7 @@ '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 @@ ) _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 @@ '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 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 @@ '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 @@ 'width', 'wrap', 'xscrollcommand', ) - def _create(self, **kwargs): + def create(self, **kwargs): return tkinter.Spinbox(self.root, **kwargs) test_show = None @@ -490,9 +490,9 @@ '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 @@ ) _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 @@ '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 @@ 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 @@ ) 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 @@ '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): @@ -946,7 +946,7 @@ ) default_orient = 'horizontal' - def _create(self, **kwargs): + def create(self, **kwargs): return tkinter.PanedWindow(self.root, **kwargs) def test_handlepad(self): @@ -1104,7 +1104,7 @@ ) _conv_pixels = noconv - def _create(self, **kwargs): + def create(self, **kwargs): return tkinter.Menu(self.root, **kwargs) def test_postcommand(self): @@ -1173,7 +1173,7 @@ ) _conv_pad_pixels = noconv - def _create(self, **kwargs): + def create(self, **kwargs): return tkinter.Message(self.root, **kwargs) def test_aspect(self): diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/test_ttk/test_extensions.py --- a/Lib/tkinter/test/test_ttk/test_extensions.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/test_ttk/test_extensions.py Sun Aug 24 09:07:47 2014 +0300 @@ -2,34 +2,30 @@ 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 @@ 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 @@ # 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 @@ 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 @@ 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 @@ def test_variable_change(self): - x = ttk.LabeledScale() + x = ttk.LabeledScale(self.root) x.pack() x.wait_visibility() x.update() @@ -151,13 +158,13 @@ # 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ # 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 @@ 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: diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/test_ttk/test_style.py --- a/Lib/tkinter/test/test_ttk/test_style.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/test_ttk/test_style.py Sun Aug 24 09:07:47 2014 +0300 @@ -2,15 +2,15 @@ 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 @@ 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) diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/test_ttk/test_widgets.py --- a/Lib/tkinter/test/test_ttk/test_widgets.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/test_ttk/test_widgets.py Sun Aug 24 09:07:47 2014 +0300 @@ -4,9 +4,9 @@ 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 @@ 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 @@ 'width', ) - def _create(self, **kwargs): + def create(self, **kwargs): return ttk.Frame(self.root, **kwargs) @@ -141,7 +137,7 @@ '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 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 @@ ) _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 @@ 'underline', 'width', ) - def _create(self, **kwargs): + def create(self, **kwargs): return ttk.Button(self.root, **kwargs) def test_default(self): @@ -225,7 +221,7 @@ 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 @@ '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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ '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 @@ 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 @@ 'underline', 'width', ) - def _create(self, **kwargs): + def create(self, **kwargs): return ttk.Menubutton(self.root, **kwargs) def test_direction(self): @@ -774,17 +754,11 @@ 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 @@ 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 @@ _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 @@ ) default_orient = 'vertical' - def _create(self, **kwargs): + def create(self, **kwargs): return ttk.Scrollbar(self.root, **kwargs) @@ -932,21 +906,13 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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('') self.assertEqual(self.nb.select(), str(self.child2)) @@ -1131,7 +1097,7 @@ 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('') else: @@ -1149,15 +1115,9 @@ 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 @@ 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 @@ 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 @@ ) default_orient = 'horizontal' - def _create(self, **kwargs): + def create(self, **kwargs): return ttk.Separator(self.root, **kwargs) @@ -1623,7 +1583,7 @@ # 'state'? ) - def _create(self, **kwargs): + def create(self, **kwargs): return ttk.Sizegrip(self.root, **kwargs) tests_gui = ( diff -r 4a6b71d8575e -r dd1dffe6f0d2 Lib/tkinter/test/widget_tests.py --- a/Lib/tkinter/test/widget_tests.py Sat Aug 23 22:21:47 2014 -0400 +++ b/Lib/tkinter/test/widget_tests.py Sun Aug 24 09:07:47 2014 +0300 @@ -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 @@ _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 @@ 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 @@ 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 @@ 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 @@ def test_variable(self): widget = self.create() - var = tkinter.DoubleVar() + var = tkinter.DoubleVar(self.root) self.checkVariableParam(widget, 'variable', var) diff -r 4a6b71d8575e -r dd1dffe6f0d2 Misc/NEWS --- a/Misc/NEWS Sat Aug 23 22:21:47 2014 -0400 +++ b/Misc/NEWS Sun Aug 24 09:07:47 2014 +0300 @@ -27,7 +27,9 @@ Library ------- --- Issue #22191: Fix warnings.__all__. +- Issue #22236: Fixed Tkinter images copying operations in NoDefaultRoot mode. + +- Issue #22191: Fix warnings.__all__. - Issue #15696: Add a __sizeof__ implementation for mmap objects on Windows. @@ -279,6 +281,9 @@ Tests ----- +- Issue #22236: Tkinter tests now don't reuse default root window. New root + window is created for every test class. + - Issue #20746: Fix test_pdb to run in refleak mode (-R). Patch by Xavier de Gaye.