From 77f19050d887d8e13c8bd3065ae0c9f2bf9d13e0 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 10 Mar 2026 12:42:56 +0200 Subject: [PATCH 1/5] gh-145736: Fix Tkinter tests for Tk 8.7, 9.0 and 9.1 --- Lib/test/test_tkinter/test_widgets.py | 168 +++++++++++--------------- Lib/test/test_tkinter/widget_tests.py | 78 +++++------- Lib/test/test_ttk/test_widgets.py | 4 +- 3 files changed, 102 insertions(+), 148 deletions(-) diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index f3579a23afc539..245ea2b1e90a4b 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -26,13 +26,11 @@ def float_round(x): return float(round(x)) class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests): - if tk_version < (9, 0): - _no_round = {'padx', 'pady'} - else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'padx', - 'pady', 'width'} - if tk_version < (9, 0): + _no_round = {'padx', 'pady'} + if tk_version < (8, 7): _clipped = {'highlightthickness'} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady'} else: _clipped = {'borderwidth', 'height', 'highlightthickness', 'padx', 'pady', 'width'} @@ -122,11 +120,6 @@ class FrameTest(AbstractToplevelTest, unittest.TestCase): 'highlightbackground', 'highlightcolor', 'highlightthickness', 'padx', 'pady', 'relief', 'takefocus', 'tile', 'visual', 'width', ) - if tk_version < (9, 0): - _no_round = {'padx', 'pady'} - else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'padx', - 'pady', 'width'} def create(self, **kwargs): return tkinter.Frame(self.root, **kwargs) @@ -142,11 +135,6 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase): 'labelanchor', 'labelwidget', 'padx', 'pady', 'relief', 'takefocus', 'text', 'visual', 'width', ) - if tk_version < (9, 0): - _no_round = {'padx', 'pady'} - else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'padx', - 'pady', 'width'} def create(self, **kwargs): return tkinter.LabelFrame(self.root, **kwargs) @@ -167,11 +155,13 @@ def test_configure_labelwidget(self): # Label, Button, Checkbutton, Radiobutton, MenuButton class AbstractLabelTest(AbstractWidgetTest, IntegerSizeTests): _rounds_pixels = False - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'height', 'highlightthickness', 'padx', 'pady', 'width'} else: - _clipped = {'borderwidth', 'insertborderwidth', 'highlightthickness', - 'padx', 'pady'} + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'insertborderwidth', 'padx', 'pady', 'width'} @add_configure_tests(StandardOptionsTests) class LabelTest(AbstractLabelTest, unittest.TestCase): @@ -201,6 +191,11 @@ class ButtonTest(AbstractLabelTest, unittest.TestCase): 'repeatdelay', 'repeatinterval', 'state', 'takefocus', 'text', 'textvariable', 'underline', 'width', 'wraplength') + if tk_version < (8, 7): + _clipped = {} + else: + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'padx', 'pady', 'width'} def create(self, **kwargs): return tkinter.Button(self.root, **kwargs) @@ -301,10 +296,12 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase): 'underline', 'width', 'wraplength', ) _rounds_pixels = (tk_version < (9, 0)) - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness', 'padx', 'pady'} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady'} else: - _clipped ={ 'insertborderwidth', 'highlightthickness', 'padx', 'pady'} + _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', 'padx', 'pady'} def create(self, **kwargs): return tkinter.Menubutton(self.root, **kwargs) @@ -316,16 +313,14 @@ def test_configure_direction(self): def test_configure_height(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'height', 100, -100, 0, conv=str) - else: - self.checkIntegerParam(widget, 'height', 0, -100, 0) + conv = str if tk_version < (8, 7) else False + self.checkIntegerParam(widget, 'height', 100, -100, 0, conv=conv) def test_configure_image(self): widget = self.create() image = tkinter.PhotoImage(master=self.root, name='image1') self.checkParam(widget, 'image', image, conv=str) - if tk_version < (9, 0): + if tk_version < (8, 7): errmsg = 'image "spam" doesn\'t exist' else: errmsg = 'image "spam" does not exist' @@ -346,10 +341,8 @@ def test_configure_menu(self): def test_configure_width(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'width', 402, -402, 0, conv=str) - else: - self.checkIntegerParam(widget, 'width', 402, 0, 0) + conv = str if tk_version < (8, 7) else False + self.checkIntegerParam(widget, 'width', 402, -402, 0, conv=conv) class OptionMenuTest(MenubuttonTest, unittest.TestCase): @@ -368,12 +361,11 @@ def test_specify_name(self): @add_configure_tests(IntegerSizeTests, StandardOptionsTests) class EntryTest(AbstractWidgetTest, unittest.TestCase): - _rounds_pixels = (tk_version < (9, 0)) - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _clipped = {'highlightthickness', 'borderwidth', 'insertborderwidth', - 'selectborderwidth'} + _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', + 'insertwidth', 'selectborderwidth'} OPTIONS = ( 'background', 'borderwidth', 'cursor', @@ -398,28 +390,21 @@ def test_configure_disabledbackground(self): def test_configure_insertborderwidth(self): widget = self.create(insertwidth=100) - if tk_version < (9, 0): - self.checkPixelsParam(widget, 'insertborderwidth', - 0, 1.3, 2.6, 6, '10p') - else: - self.checkPixelsParam(widget, 'insertborderwidth', - 0, 1.3, 3, 6, '10p') - self.checkParam(widget, 'insertborderwidth', -2) + self.checkPixelsParam(widget, 'insertborderwidth', + 0, 1.3, 2.6, 6, -2, '10p') # insertborderwidth is bounded above by a half of insertwidth. - expected = 100 // 2 if tk_version < (9, 0) else 60 + expected = 100 // 2 if tk_version < (8, 7) else 60 self.checkParam(widget, 'insertborderwidth', 60, expected=expected) def test_configure_insertwidth(self): widget = self.create() - self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, '10p') - if tk_version < (9, 0): + self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, 0.9, '10p') + if tk_version < (8, 7): + self.checkParam(widget, 'insertwidth', 0, expected=2) self.checkParam(widget, 'insertwidth', 0.1, expected=2) self.checkParam(widget, 'insertwidth', -2, expected=2) - self.checkParam(widget, 'insertwidth', 0.9, expected=1) else: - self.checkParam(widget, 'insertwidth', 0.1) - self.checkParam(widget, 'insertwidth', -2, expected=0) - self.checkParam(widget, 'insertwidth', 0.9) + self.checkPixelsParam(widget, 'insertwidth', 0, 0.1, -2) def test_configure_invalidcommand(self): widget = self.create() @@ -562,7 +547,7 @@ def test_configure_values(self): # XXX widget = self.create() self.assertEqual(widget['values'], '') - if tk_version < (9, 0): + if tk_version < (8, 7): expected = 'mon tue wed thur' else: expected = ('mon', 'tue', 'wed', 'thur') @@ -571,7 +556,7 @@ def test_configure_values(self): self.checkParam(widget, 'values', ('mon', 'tue', 'wed', 'thur'), expected=expected) - if tk_version < (9, 0): + if tk_version < (8, 7): expected = '42 3.14 {} {any string}' else: expected = (42, 3.14, '', 'any string') @@ -640,9 +625,13 @@ class TextTest(AbstractWidgetTest, unittest.TestCase): 'tabs', 'tabstyle', 'takefocus', 'undo', 'width', 'wrap', 'xscrollcommand', 'yscrollcommand', ) - _rounds_pixels = (tk_version < (9, 0)) _no_round = {'selectborderwidth'} - _clipped = {'highlightthickness'} + if tk_version < (9, 0): + _clipped = {'highlightthickness', 'spacing1', 'spacing2', 'spacing3'} + else: + _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', + 'insertwidth', 'padx', 'pady', 'selectborderwidth', + 'spacing1', 'spacing2', 'spacing3'} def create(self, **kwargs): return tkinter.Text(self.root, **kwargs) @@ -672,8 +661,11 @@ def test_configure_height(self): widget = self.create() self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, '3c') expected = 1 if tk_version < (9, 0) else 0 - self.checkParam(widget, 'height', -100, expected=expected) self.checkParam(widget, 'height', 0, expected=expected) + if tk_version < (9, 1): + self.checkParam(widget, 'height', -100, expected=expected) + else: + self.checkInvalidParam(widget, 'height', -100) def test_configure_maxundo(self): widget = self.create() @@ -691,24 +683,20 @@ def test_configure_insertunfocussed(self): def test_configure_selectborderwidth(self): widget = self.create() - value = -2 if tk_version < (9, 0) else 0 self.checkPixelsParam(widget, 'selectborderwidth', - 1.3, 2.6, value, '10p', conv=False) + 1.3, 2.6, -2, '10p', conv=False) def test_configure_spacing1(self): widget = self.create() - self.checkPixelsParam(widget, 'spacing1', 20, 21.4, 22.6, '0.5c') - self.checkParam(widget, 'spacing1', -5, expected=0) + self.checkPixelsParam(widget, 'spacing1', 20, 21.4, 22.6, -5, '0.5c') def test_configure_spacing2(self): widget = self.create() - self.checkPixelsParam(widget, 'spacing2', 5, 6.4, 7.6, '0.1c') - self.checkParam(widget, 'spacing2', -1, expected=0) + self.checkPixelsParam(widget, 'spacing2', 5, 6.4, 7.6, -1, '0.1c') def test_configure_spacing3(self): widget = self.create() - self.checkPixelsParam(widget, 'spacing3', 20, 21.4, 22.6, '0.5c') - self.checkParam(widget, 'spacing3', -10, expected=0) + self.checkPixelsParam(widget, 'spacing3', 20, 21.4, 22.6, -10, '0.5c') def test_configure_startline(self): widget = self.create() @@ -781,15 +769,16 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase): 'xscrollcommand', 'xscrollincrement', 'yscrollcommand', 'yscrollincrement', 'width', ) - _rounds_pixels = True - if tk_version < (9, 0): - _noround = {} + if tk_version < (8, 7): _clipped = {'highlightthickness'} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', + 'insertwidth', 'selectborderwidth', 'xscrollincrement', + 'yscrollincrement'} else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'width', - 'xscrollincrement', 'yscrollincrement'} - _clipped = {'borderwidth', 'height', 'highlightthickness', 'width', - 'xscrollincrement', 'yscrollincrement'} + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'insertborderwidth', 'insertwidth', 'selectborderwidth', + 'width', 'xscrollincrement', 'yscrollincrement'} _stringify = True def create(self, **kwargs): @@ -938,7 +927,6 @@ def test_create_line(self): def test_create_polygon(self): c = self.create() - tk87 = tk_version >= (8, 7) # In Tk < 8.7 polygons are filled, but has no outline by default. # This affects its size, so always explicitly specify outline. i1 = c.create_polygon(20, 30, 40, 50, 60, 10, outline='red') @@ -1043,11 +1031,10 @@ class ListboxTest(AbstractWidgetTest, unittest.TestCase): 'selectmode', 'setgrid', 'state', 'takefocus', 'width', 'xscrollcommand', 'yscrollcommand', ) - _rounds_pixels = (tk_version < (9, 0)) - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _clipped = { 'borderwidth', 'highlightthickness', 'selectborderwidth'} + _clipped = {'borderwidth', 'highlightthickness', 'selectborderwidth'} def create(self, **kwargs): return tkinter.Listbox(self.root, **kwargs) @@ -1185,7 +1172,6 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase): 'resolution', 'showvalue', 'sliderlength', 'sliderrelief', 'state', 'takefocus', 'tickinterval', 'to', 'troughcolor', 'variable', 'width', ) - _rounds_pixels = (tk_version < (9, 0)) _clipped = {'highlightthickness'} default_orient = 'vertical' @@ -1255,12 +1241,10 @@ class ScrollbarTest(AbstractWidgetTest, unittest.TestCase): 'repeatdelay', 'repeatinterval', 'takefocus', 'troughcolor', 'width', ) - _rounds_pixels = True - if tk_version >= (9, 0): - _no_round = {'borderwidth', 'elementborderwidth', 'highlightthickness', - 'width'} - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'highlightthickness'} else: _clipped = {'borderwidth', 'highlightthickness', 'width'} _stringify = True @@ -1272,8 +1256,7 @@ def create(self, **kwargs): def test_configure_elementborderwidth(self): widget = self.create() self.checkPixelsParam(widget, 'elementborderwidth', 4.3, 5.6, '1m') - expected = self._default_pixels if tk_version >= (8, 7) else -2 - self.checkParam(widget, 'elementborderwidth', -2, expected=expected) + self.checkNegPixelParam(widget, 'elementborderwidth', -2) def test_configure_orient(self): widget = self.create() @@ -1311,14 +1294,8 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase): 'sashcursor', 'sashpad', 'sashrelief', 'sashwidth', 'showhandle', 'width', ) - _rounds_pixels = True - if tk_version < (9, 0): - _no_round = {'handlesize', 'height', 'proxyborderwidth', 'sashwidth', - 'selectborderwidth', 'width'} - else: - _no_round = {'borderwidth', 'handlepad', 'handlesize', 'height', - 'proxyborderwidth', 'sashpad', 'sashwidth', - 'selectborderwidth', 'width'} + _no_round = {'handlesize', 'height', 'proxyborderwidth', 'sashwidth', + 'selectborderwidth', 'width'} _clipped = {} default_orient = 'horizontal' @@ -1568,12 +1545,11 @@ class MessageTest(AbstractWidgetTest, unittest.TestCase): 'justify', 'padx', 'pady', 'relief', 'takefocus', 'text', 'textvariable', 'width', ) - _rounds_pixels = (tk_version < (9, 0)) _no_round = {'padx', 'pady'} - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady'} + _clipped = {'borderwidth', 'highlightthickness', 'width'} def create(self, **kwargs): return tkinter.Message(self.root, **kwargs) @@ -1585,20 +1561,16 @@ def test_configure_aspect(self): def test_configure_padx(self): widget = self.create() self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m') - expected = -2 if tk_version < (9, 0) else self._default_pixels - self.checkParam(widget, 'padx', -2, expected=expected) + self.checkNegPixelParam(widget, 'padx', -2) def test_configure_pady(self): widget = self.create() self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m') - expected = -2 if tk_version < (9, 0) else self._default_pixels - self.checkParam(widget, 'pady', -2, expected=expected) + self.checkNegPixelParam(widget, 'pady', -2) def test_configure_width(self): widget = self.create() - self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, 0, '5i') - expected = 0 if tk_version >= (8, 7) else -402 - self.checkParam(widget, 'width', -402, expected=expected) + self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, 0, -402, '5i') class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): diff --git a/Lib/test/test_tkinter/widget_tests.py b/Lib/test/test_tkinter/widget_tests.py index dd2d7c4da459ab..e84ce654b7bcbe 100644 --- a/Lib/test/test_tkinter/widget_tests.py +++ b/Lib/test/test_tkinter/widget_tests.py @@ -12,8 +12,8 @@ # borderwidth = bd class AbstractWidgetTest(AbstractTkTest): - _default_pixels = '' # Value for unset pixel options. - _rounds_pixels = True # True if some pixel options are rounded. + _default_pixels = '' if tk_version >= (9, 0) else -1 # Value for unset pixel options. + _rounds_pixels = (tk_version < (9, 0)) # True if some pixel options are rounded. _no_round = {} # Pixel options which are not rounded nonetheless _stringify = False # Whether to convert tuples to strings _allow_empty_justify = False @@ -73,6 +73,14 @@ def checkInvalidParam(self, widget, name, value, errmsg=None): widget.configure({name: value}) self.assertEqual(widget[name], orig) + def checkNegPixelParam(self, widget, name, value): + if tk_version < (8, 7): + self.checkParam(widget, name, value) + elif tk_version < (9, 1): + self.checkParam(widget, name, value, expected=self._default_pixels) + else: + self.checkInvalidParam(widget, name, value) + def checkParams(self, widget, name, *values, **kwargs): for value in values: self.checkParam(widget, name, value, **kwargs) @@ -143,10 +151,10 @@ def checkEnumParam(self, widget, name, *values, self.checkInvalidParam(widget, name, 'spam', errmsg=errmsg) def checkPixelsParam(self, widget, name, *values, conv=None, **kwargs): - if not self._rounds_pixels or name in self._no_round: - conv = False - elif conv != str: - conv = round + if conv is None: + if self._rounds_pixels and name not in self._no_round: + conv = round + alow_neg = tk_version < (9, 1) for value in values: expected = _sentinel conv1 = conv @@ -156,6 +164,9 @@ def checkPixelsParam(self, widget, name, *values, conv=None, **kwargs): if conv1 and conv1 is not str: expected = pixels_conv(value) * self.scaling conv1 = round + elif not alow_neg and isinstance(value, (int, float)) and value < 0: + self.checkInvalidParam(widget, name, value) + continue self.checkParam(widget, name, value, expected=expected, conv=conv1, **kwargs) errmsg = '(bad|expected) screen distance ((or "" )?but got )?"{}"' @@ -177,7 +188,7 @@ def checkReliefParam(self, widget, name, *, allow_empty=False): def checkImageParam(self, widget, name): image = tkinter.PhotoImage(master=self.root, name='image1') self.checkParam(widget, name, image, conv=str) - if tk_version < (9, 0): + if tk_version < (8, 7): errmsg = 'image "spam" doesn\'t exist' else: errmsg = 'image "spam" does not exist' @@ -246,11 +257,7 @@ def test_configure_activeborderwidth(self): def test_configure_borderwidth(self): widget = self.create() self.checkPixelsParam(widget, 'borderwidth', - 0, 1.3, 2.6, 6, '10p') - if tk_version < (9, 0): - self.checkParam(widget, 'borderwidth', -2) - else: - self.checkParam(widget, 'borderwidth', 0) + 0, 1.3, 2.6, 6, -2, '10p') if 'bd' in self.OPTIONS: self.checkPixelsParam(widget, 'bd', 0, 1.3, 2.6, 6, '10p') @@ -259,50 +266,27 @@ def test_configure_borderwidth(self): def test_configure_highlightthickness(self): widget = self.create() self.checkPixelsParam(widget, 'highlightthickness', - 0, 1.3, 2.6, 6, '10p') - self.checkParam(widget, 'highlightthickness', -2) + 0, 1.3, 2.6, 6, -2, '10p') def test_configure_insertborderwidth(self): widget = self.create() - if tk_version < (9, 0): - values = (0, 1.3, 2.6, 6, -2, '10p') - value = -2 - else: - values = (0, 1, 3, 6, 13) - value = 0 - self.checkPixelsParam(widget, 'insertborderwidth', *values) - self.checkParam(widget, 'insertborderwidth', value) + self.checkPixelsParam(widget, 'insertborderwidth', 0, 1.3, 2.6, 6, -2, '10p') def test_configure_insertwidth(self): widget = self.create() - if tk_version < (9, 0): - self.checkPixelsParam(widget, 'insertwidth', 1.3, 2.6, -2, '10p') - else: - self.checkPixelsParam(widget, 'insertwidth', 1, 3, 0, 13) + self.checkPixelsParam(widget, 'insertwidth', 1.3, 2.6, -2, '10p') def test_configure_padx(self): widget = self.create() - self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m') - if tk_version < (9, 0): - self.checkParam(widget, 'padx', -2) - else: - self.checkParam(widget, 'padx', 0) + self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, -2, '12m') def test_configure_pady(self): widget = self.create() - self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m') - if tk_version < (9, 0): - self.checkParam(widget, 'pady', -2) - else: - self.checkParam(widget, 'pady', 0) + self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, -2, '12m') def test_configure_selectborderwidth(self): widget = self.create() - if tk_version < (9, 0): - values = (1.3, 2.6, -2, '10p') - else: - values = (1, 3, 0, 13) - self.checkPixelsParam(widget, 'selectborderwidth', *values) + self.checkPixelsParam(widget, 'selectborderwidth', 1.3, 2.6, -2, '10p') class StandardOptionsTests(PixelOptionsTests): @@ -569,14 +553,12 @@ class IntegerSizeTests: """ Tests widgets which only accept integral width and height.""" def test_configure_height(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'height', 100, -100, 0) - else: - self.checkIntegerParam(widget, 'height', 100, 0, 0) + self.checkIntegerParam(widget, 'height', 100, -100, 0) def test_configure_width(self): widget = self.create() - if tk_version < (9, 0): + self.checkIntegerParam(widget, 'width', 402, -402, 0) + if tk_version < (8, 7): self.checkIntegerParam(widget, 'width', 402, -402, 0) else: self.checkIntegerParam(widget, 'width', 402, 0, 0) @@ -586,14 +568,14 @@ class PixelSizeTests: """ Tests widgets which accept screen distances for width and height.""" def test_configure_height(self): widget = self.create() - value = -100 if tk_version < (9, 0) else 0 + value = -100 if tk_version < (8, 7) else 0 self.checkPixelsParam( widget, 'height', 100, 101.2, 102.6, value, 0, '3c' ) def test_configure_width(self): widget = self.create() - value = -402 if tk_version < (9, 0) else 0 + value = -402 if tk_version < (8, 7) else 0 self.checkPixelsParam( widget, 'width', 402, 403.4, 404.6, value, 0, '5i' ) diff --git a/Lib/test/test_ttk/test_widgets.py b/Lib/test/test_ttk/test_widgets.py index e738fbff82ed43..8cce9aed9d514f 100644 --- a/Lib/test/test_ttk/test_widgets.py +++ b/Lib/test/test_ttk/test_widgets.py @@ -183,7 +183,7 @@ def checkImageParam(self, widget, name): expected=('image1', 'active', 'image2')) self.checkParam(widget, name, 'image1 active image2', expected=('image1', 'active', 'image2')) - if tk_version < (9, 0): + if tk_version < (8, 7): errmsg = 'image "spam" doesn\'t exist' else: errmsg = 'image "spam" does not exist' @@ -1192,7 +1192,7 @@ def test_traversal(self): elif sys.platform == 'win32': focus_identify_as = 'focus' else: - focus_identify_as = 'focus' if tk_version < (9,0) else 'padding' + focus_identify_as = 'focus' if tk_version < (8, 7) else 'padding' self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) self.nb.focus_force() From 2fb92a3a070eedf0e7b9ed956173c16100e2fad8 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 10 Mar 2026 13:33:31 +0200 Subject: [PATCH 2/5] Clean up more tests. --- Lib/test/test_tkinter/test_widgets.py | 6 ------ Lib/test/test_tkinter/widget_tests.py | 14 ++------------ 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index 245ea2b1e90a4b..6b4e15d6e66fd6 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -29,8 +29,6 @@ class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests): _no_round = {'padx', 'pady'} if tk_version < (8, 7): _clipped = {'highlightthickness'} - elif tk_version < (9, 0): - _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady'} else: _clipped = {'borderwidth', 'height', 'highlightthickness', 'padx', 'pady', 'width'} @@ -771,10 +769,6 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase): ) if tk_version < (8, 7): _clipped = {'highlightthickness'} - elif tk_version < (9, 0): - _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', - 'insertwidth', 'selectborderwidth', 'xscrollincrement', - 'yscrollincrement'} else: _clipped = {'borderwidth', 'height', 'highlightthickness', 'insertborderwidth', 'insertwidth', 'selectborderwidth', diff --git a/Lib/test/test_tkinter/widget_tests.py b/Lib/test/test_tkinter/widget_tests.py index e84ce654b7bcbe..b39b1ac4a94de4 100644 --- a/Lib/test/test_tkinter/widget_tests.py +++ b/Lib/test/test_tkinter/widget_tests.py @@ -558,27 +558,17 @@ def test_configure_height(self): def test_configure_width(self): widget = self.create() self.checkIntegerParam(widget, 'width', 402, -402, 0) - if tk_version < (8, 7): - self.checkIntegerParam(widget, 'width', 402, -402, 0) - else: - self.checkIntegerParam(widget, 'width', 402, 0, 0) class PixelSizeTests: """ Tests widgets which accept screen distances for width and height.""" def test_configure_height(self): widget = self.create() - value = -100 if tk_version < (8, 7) else 0 - self.checkPixelsParam( - widget, 'height', 100, 101.2, 102.6, value, 0, '3c' - ) + self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '3c') def test_configure_width(self): widget = self.create() - value = -402 if tk_version < (8, 7) else 0 - self.checkPixelsParam( - widget, 'width', 402, 403.4, 404.6, value, 0, '5i' - ) + self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i') def add_configure_tests(*source_classes): From 65843f79acdd367a4fb55081bb334e57298b1d3f Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 10 Mar 2026 23:44:31 +0200 Subject: [PATCH 3/5] Clean up yet more tests. --- Lib/test/test_tkinter/test_widgets.py | 36 ++++++++++----------------- Lib/test/test_tkinter/widget_tests.py | 18 ++++++-------- 2 files changed, 20 insertions(+), 34 deletions(-) diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index 6b4e15d6e66fd6..c551a73d732238 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -627,9 +627,9 @@ class TextTest(AbstractWidgetTest, unittest.TestCase): if tk_version < (9, 0): _clipped = {'highlightthickness', 'spacing1', 'spacing2', 'spacing3'} else: - _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', - 'insertwidth', 'padx', 'pady', 'selectborderwidth', - 'spacing1', 'spacing2', 'spacing3'} + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'insertborderwidth', 'insertwidth', 'padx', 'pady', + 'selectborderwidth', 'spacing1', 'spacing2', 'spacing3'} def create(self, **kwargs): return tkinter.Text(self.root, **kwargs) @@ -658,12 +658,11 @@ def test_configure_endline(self): def test_configure_height(self): widget = self.create() self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, '3c') - expected = 1 if tk_version < (9, 0) else 0 - self.checkParam(widget, 'height', 0, expected=expected) - if tk_version < (9, 1): - self.checkParam(widget, 'height', -100, expected=expected) + if tk_version < (9, 0): + self.checkParam(widget, 'height', 0, expected=1) + self.checkParam(widget, 'height', -100, expected=1) else: - self.checkInvalidParam(widget, 'height', -100) + self.checkPixelsParam(widget, 'height', 0, -100) def test_configure_maxundo(self): widget = self.create() @@ -1238,9 +1237,10 @@ class ScrollbarTest(AbstractWidgetTest, unittest.TestCase): if tk_version < (8, 7): _clipped = {'highlightthickness'} elif tk_version < (9, 0): - _clipped = {'borderwidth', 'highlightthickness'} + _clipped = {'borderwidth', 'elementborderwidth', 'highlightthickness'} else: - _clipped = {'borderwidth', 'highlightthickness', 'width'} + _clipped = {'borderwidth', 'elementborderwidth', 'highlightthickness', 'width'} + _clipped_to_default = {'elementborderwidth'} _stringify = True default_orient = 'vertical' @@ -1249,8 +1249,7 @@ def create(self, **kwargs): def test_configure_elementborderwidth(self): widget = self.create() - self.checkPixelsParam(widget, 'elementborderwidth', 4.3, 5.6, '1m') - self.checkNegPixelParam(widget, 'elementborderwidth', -2) + self.checkPixelsParam(widget, 'elementborderwidth', 4.3, 5.6, -2, '1m') def test_configure_orient(self): widget = self.create() @@ -1543,7 +1542,8 @@ class MessageTest(AbstractWidgetTest, unittest.TestCase): if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _clipped = {'borderwidth', 'highlightthickness', 'width'} + _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady', 'width'} + _clipped_to_default = {'padx', 'pady'} def create(self, **kwargs): return tkinter.Message(self.root, **kwargs) @@ -1552,16 +1552,6 @@ def test_configure_aspect(self): widget = self.create() self.checkIntegerParam(widget, 'aspect', 250, 0, -300) - def test_configure_padx(self): - widget = self.create() - self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m') - self.checkNegPixelParam(widget, 'padx', -2) - - def test_configure_pady(self): - widget = self.create() - self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m') - self.checkNegPixelParam(widget, 'pady', -2) - def test_configure_width(self): widget = self.create() self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, 0, -402, '5i') diff --git a/Lib/test/test_tkinter/widget_tests.py b/Lib/test/test_tkinter/widget_tests.py index b39b1ac4a94de4..17fa2c7be8c0bd 100644 --- a/Lib/test/test_tkinter/widget_tests.py +++ b/Lib/test/test_tkinter/widget_tests.py @@ -17,6 +17,7 @@ class AbstractWidgetTest(AbstractTkTest): _no_round = {} # Pixel options which are not rounded nonetheless _stringify = False # Whether to convert tuples to strings _allow_empty_justify = False + _clipped_to_default = {} @property def scaling(self): @@ -43,9 +44,12 @@ def checkParam(self, widget, name, value, *, expected=_sentinel, widget[name] = value if expected is _sentinel: expected = value - if name in self._clipped: - if not isinstance(expected, str): - expected = max(expected, 0) + if name in self._clipped: + if not isinstance(expected, str) and expected < 0: + if tk_version >= (8, 7) and name in self._clipped_to_default: + expected = self._default_pixels + else: + expected = 0 if conv: expected = conv(expected) if self._stringify or not self.wantobjects: @@ -73,14 +77,6 @@ def checkInvalidParam(self, widget, name, value, errmsg=None): widget.configure({name: value}) self.assertEqual(widget[name], orig) - def checkNegPixelParam(self, widget, name, value): - if tk_version < (8, 7): - self.checkParam(widget, name, value) - elif tk_version < (9, 1): - self.checkParam(widget, name, value, expected=self._default_pixels) - else: - self.checkInvalidParam(widget, name, value) - def checkParams(self, widget, name, *values, **kwargs): for value in values: self.checkParam(widget, name, value, **kwargs) From 382543de90c2ae78d38c7986502f9fa41b4d71a0 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 11 Mar 2026 09:07:48 +0200 Subject: [PATCH 4/5] Clean up even more tests. --- Lib/test/test_tkinter/test_widgets.py | 30 ++++----------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index c551a73d732238..e7a147f074cd9e 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -678,11 +678,6 @@ def test_configure_insertunfocussed(self): self.checkEnumParam(widget, 'insertunfocussed', 'hollow', 'none', 'solid') - def test_configure_selectborderwidth(self): - widget = self.create() - self.checkPixelsParam(widget, 'selectborderwidth', - 1.3, 2.6, -2, '10p', conv=False) - def test_configure_spacing1(self): widget = self.create() self.checkPixelsParam(widget, 'spacing1', 20, 21.4, 22.6, -5, '0.5c') @@ -1276,7 +1271,7 @@ def test_set(self): self.assertRaises(TypeError, sb.set, 0.6, 0.7, 0.8) -@add_configure_tests(StandardOptionsTests) +@add_configure_tests(PixelSizeTests, StandardOptionsTests) class PanedWindowTest(AbstractWidgetTest, unittest.TestCase): OPTIONS = ( 'background', 'borderwidth', 'cursor', @@ -1301,13 +1296,7 @@ def test_configure_handlepad(self): def test_configure_handlesize(self): widget = self.create() - self.checkPixelsParam(widget, 'handlesize', 8, 9.4, 10.6, -3, '2m', - conv=False) - - def test_configure_height(self): - widget = self.create() - self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i', - conv=False) + self.checkPixelsParam(widget, 'handlesize', 8, 9.4, 10.6, -3, '2m') def test_configure_opaqueresize(self): widget = self.create() @@ -1322,8 +1311,7 @@ def test_configure_proxybackground(self): def test_configure_proxyborderwidth(self): widget = self.create() self.checkPixelsParam(widget, 'proxyborderwidth', - 0, 1.3, 2.9, 6, -2, '10p', - conv=False) + 0, 1.3, 2.9, 6, -2, '10p') @requires_tk(8, 6, 5) def test_configure_proxyrelief(self): @@ -1345,18 +1333,12 @@ def test_configure_sashrelief(self): def test_configure_sashwidth(self): widget = self.create() - self.checkPixelsParam(widget, 'sashwidth', 10, 11.1, 15.6, -3, '1m', - conv=False) + self.checkPixelsParam(widget, 'sashwidth', 10, 11.1, 15.6, -3, '1m') def test_configure_showhandle(self): widget = self.create() self.checkBooleanParam(widget, 'showhandle') - def test_configure_width(self): - widget = self.create() - self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i', - conv=False) - def create2(self): p = self.create() b = tkinter.Button(p) @@ -1552,10 +1534,6 @@ def test_configure_aspect(self): widget = self.create() self.checkIntegerParam(widget, 'aspect', 250, 0, -300) - def test_configure_width(self): - widget = self.create() - self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, 0, -402, '5i') - class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): From 2140325ef4f85872d60c69c731ef0d2c097b252f Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 11 Mar 2026 11:12:37 +0200 Subject: [PATCH 5/5] Fix tests for Tk 9.0.0 and 9.0.1. --- Lib/test/test_tkinter/test_widgets.py | 40 ++++++++++++++++++++++++--- Lib/test/test_tkinter/widget_tests.py | 4 +-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index e7a147f074cd9e..1c400e970eb02d 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -161,6 +161,12 @@ class AbstractLabelTest(AbstractWidgetTest, IntegerSizeTests): _clipped = {'borderwidth', 'height', 'highlightthickness', 'insertborderwidth', 'padx', 'pady', 'width'} + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 2): + self._clipped = self._clipped - {'height', 'width'} + + @add_configure_tests(StandardOptionsTests) class LabelTest(AbstractLabelTest, unittest.TestCase): OPTIONS = ( @@ -301,6 +307,11 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase): else: _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', 'padx', 'pady'} + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1): + self._clipped = self._clipped - {'borderwidth'} + def create(self, **kwargs): return tkinter.Menubutton(self.root, **kwargs) @@ -311,7 +322,10 @@ def test_configure_direction(self): def test_configure_height(self): widget = self.create() - conv = str if tk_version < (8, 7) else False + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): + conv = str + else: + conv = False self.checkIntegerParam(widget, 'height', 100, -100, 0, conv=conv) def test_configure_image(self): @@ -339,7 +353,10 @@ def test_configure_menu(self): def test_configure_width(self): widget = self.create() - conv = str if tk_version < (8, 7) else False + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): + conv = str + else: + conv = False self.checkIntegerParam(widget, 'width', 402, -402, 0, conv=conv) @@ -545,7 +562,7 @@ def test_configure_values(self): # XXX widget = self.create() self.assertEqual(widget['values'], '') - if tk_version < (8, 7): + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): expected = 'mon tue wed thur' else: expected = ('mon', 'tue', 'wed', 'thur') @@ -554,7 +571,7 @@ def test_configure_values(self): self.checkParam(widget, 'values', ('mon', 'tue', 'wed', 'thur'), expected=expected) - if tk_version < (8, 7): + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): expected = '42 3.14 {} {any string}' else: expected = (42, 3.14, '', 'any string') @@ -631,6 +648,13 @@ class TextTest(AbstractWidgetTest, unittest.TestCase): 'insertborderwidth', 'insertwidth', 'padx', 'pady', 'selectborderwidth', 'spacing1', 'spacing2', 'spacing3'} + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 2): + self._clipped = self._clipped - {'borderwidth', 'height', 'padx', 'pady'} + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1): + self._clipped = self._clipped - {'insertborderwidth', 'insertwidth', 'selectborderwidth'} + def create(self, **kwargs): return tkinter.Text(self.root, **kwargs) @@ -769,6 +793,14 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase): 'width', 'xscrollincrement', 'yscrollincrement'} _stringify = True + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1): + self._rounds_pixels = True + self._no_round = {'borderwidth', 'height', 'highlightthickness', + 'width', 'xscrollincrement', 'yscrollincrement'} + self._clipped = self._clipped - {'insertborderwidth', 'insertwidth', 'selectborderwidth'} + def create(self, **kwargs): return tkinter.Canvas(self.root, **kwargs) diff --git a/Lib/test/test_tkinter/widget_tests.py b/Lib/test/test_tkinter/widget_tests.py index 17fa2c7be8c0bd..94244a8b3fe244 100644 --- a/Lib/test/test_tkinter/widget_tests.py +++ b/Lib/test/test_tkinter/widget_tests.py @@ -14,10 +14,10 @@ class AbstractWidgetTest(AbstractTkTest): _default_pixels = '' if tk_version >= (9, 0) else -1 # Value for unset pixel options. _rounds_pixels = (tk_version < (9, 0)) # True if some pixel options are rounded. - _no_round = {} # Pixel options which are not rounded nonetheless + _no_round = set() # Pixel options which are not rounded nonetheless _stringify = False # Whether to convert tuples to strings _allow_empty_justify = False - _clipped_to_default = {} + _clipped_to_default = set() @property def scaling(self):