gh-124111: Update tkinter for compatibility with Tcl/Tk 9.0.0 (GH-124156)

This commit is contained in:
Marc Culler 2024-11-14 12:45:08 -06:00 committed by GitHub
parent 1e3497e745
commit 47cbf03885
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 337 additions and 194 deletions

View File

@ -66,9 +66,10 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
f.tk_busy_forget() f.tk_busy_forget()
self.assertFalse(f.tk_busy_status()) self.assertFalse(f.tk_busy_status())
self.assertFalse(f.tk_busy_current()) self.assertFalse(f.tk_busy_current())
with self.assertRaisesRegex(TclError, "can't find busy window"): errmsg = r"can(no|')t find busy window.*"
with self.assertRaisesRegex(TclError, errmsg):
f.tk_busy_configure() f.tk_busy_configure()
with self.assertRaisesRegex(TclError, "can't find busy window"): with self.assertRaisesRegex(TclError, errmsg):
f.tk_busy_forget() f.tk_busy_forget()
@requires_tk(8, 6, 6) @requires_tk(8, 6, 6)
@ -87,7 +88,8 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
self.assertEqual(f.tk_busy_configure('cursor')[4], 'heart') self.assertEqual(f.tk_busy_configure('cursor')[4], 'heart')
f.tk_busy_forget() f.tk_busy_forget()
with self.assertRaisesRegex(TclError, "can't find busy window"): errmsg = r"can(no|')t find busy window.*"
with self.assertRaisesRegex(TclError, errmsg):
f.tk_busy_cget('cursor') f.tk_busy_cget('cursor')
def test_tk_setPalette(self): def test_tk_setPalette(self):

View File

@ -7,9 +7,13 @@ from test.support import requires
from test.test_tkinter.support import (requires_tk, tk_version, from test.test_tkinter.support import (requires_tk, tk_version,
get_tk_patchlevel, widget_eq, get_tk_patchlevel, widget_eq,
AbstractDefaultRootTest) AbstractDefaultRootTest)
from test.test_tkinter.widget_tests import ( from test.test_tkinter.widget_tests import (
add_standard_options, add_configure_tests,
AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests) AbstractWidgetTest,
StandardOptionsTests,
IntegerSizeTests,
PixelSizeTests)
requires('gui') requires('gui')
@ -20,9 +24,17 @@ EXPECTED_SCREEN_DISTANCE_OR_EMPTY_ERRMSG = '(bad|expected) screen distance (or "
def float_round(x): def float_round(x):
return float(round(x)) return float(round(x))
class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests): class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests):
_conv_pad_pixels = False if tk_version < (9, 0):
_no_round = {'padx', 'pady'}
else:
_no_round = {'borderwidth', 'height', 'highlightthickness', 'padx',
'pady', 'width'}
if tk_version < (9, 0):
_clipped = {'highlightthickness'}
else:
_clipped = {'borderwidth', 'height', 'highlightthickness', 'padx',
'pady', 'width'}
def test_configure_class(self): def test_configure_class(self):
widget = self.create() widget = self.create()
@ -58,7 +70,7 @@ class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests):
self.assertEqual(widget2['visual'], 'default') self.assertEqual(widget2['visual'], 'default')
@add_standard_options(StandardOptionsTests) @add_configure_tests(StandardOptionsTests)
class ToplevelTest(AbstractToplevelTest, unittest.TestCase): class ToplevelTest(AbstractToplevelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'background', 'backgroundimage', 'borderwidth', 'background', 'backgroundimage', 'borderwidth',
@ -101,7 +113,7 @@ class ToplevelTest(AbstractToplevelTest, unittest.TestCase):
self.assertEqual(widget2['use'], wid) self.assertEqual(widget2['use'], wid)
@add_standard_options(StandardOptionsTests) @add_configure_tests(StandardOptionsTests)
class FrameTest(AbstractToplevelTest, unittest.TestCase): class FrameTest(AbstractToplevelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'background', 'backgroundimage', 'borderwidth', 'background', 'backgroundimage', 'borderwidth',
@ -109,12 +121,17 @@ class FrameTest(AbstractToplevelTest, unittest.TestCase):
'highlightbackground', 'highlightcolor', 'highlightthickness', 'highlightbackground', 'highlightcolor', 'highlightthickness',
'padx', 'pady', 'relief', 'takefocus', 'tile', 'visual', 'width', '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): def create(self, **kwargs):
return tkinter.Frame(self.root, **kwargs) return tkinter.Frame(self.root, **kwargs)
@add_standard_options(StandardOptionsTests) @add_configure_tests(StandardOptionsTests)
class LabelFrameTest(AbstractToplevelTest, unittest.TestCase): class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'background', 'borderwidth', 'background', 'borderwidth',
@ -124,6 +141,11 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
'labelanchor', 'labelwidget', 'padx', 'pady', 'relief', 'labelanchor', 'labelwidget', 'padx', 'pady', 'relief',
'takefocus', 'text', 'visual', 'width', '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): def create(self, **kwargs):
return tkinter.LabelFrame(self.root, **kwargs) return tkinter.LabelFrame(self.root, **kwargs)
@ -141,15 +163,16 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
self.checkParam(widget, 'labelwidget', label, expected='.foo') self.checkParam(widget, 'labelwidget', label, expected='.foo')
label.destroy() label.destroy()
# Label, Button, Checkbutton, Radiobutton, MenuButton
class AbstractLabelTest(AbstractWidgetTest, IntegerSizeTests): class AbstractLabelTest(AbstractWidgetTest, IntegerSizeTests):
_conv_pixels = False _rounds_pixels = False
_clip_highlightthickness = tk_version >= (8, 7) if tk_version < (9, 0):
_clip_pad = tk_version >= (8, 7) _clipped = {}
_clip_borderwidth = tk_version >= (8, 7) else:
_clipped = {'borderwidth', 'insertborderwidth', 'highlightthickness',
'padx', 'pady'}
@add_configure_tests(StandardOptionsTests)
@add_standard_options(StandardOptionsTests)
class LabelTest(AbstractLabelTest, unittest.TestCase): class LabelTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'activebackground', 'activeforeground', 'anchor', 'activebackground', 'activeforeground', 'anchor',
@ -165,7 +188,7 @@ class LabelTest(AbstractLabelTest, unittest.TestCase):
return tkinter.Label(self.root, **kwargs) return tkinter.Label(self.root, **kwargs)
@add_standard_options(StandardOptionsTests) @add_configure_tests(StandardOptionsTests)
class ButtonTest(AbstractLabelTest, unittest.TestCase): class ButtonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'activebackground', 'activeforeground', 'anchor', 'activebackground', 'activeforeground', 'anchor',
@ -186,7 +209,7 @@ class ButtonTest(AbstractLabelTest, unittest.TestCase):
self.checkEnumParam(widget, 'default', 'active', 'disabled', 'normal') self.checkEnumParam(widget, 'default', 'active', 'disabled', 'normal')
@add_standard_options(StandardOptionsTests) @add_configure_tests(StandardOptionsTests)
class CheckbuttonTest(AbstractLabelTest, unittest.TestCase): class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'activebackground', 'activeforeground', 'anchor', 'activebackground', 'activeforeground', 'anchor',
@ -240,8 +263,7 @@ class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
b2.deselect() b2.deselect()
self.assertEqual(v.get(), 0) self.assertEqual(v.get(), 0)
@add_configure_tests(StandardOptionsTests)
@add_standard_options(StandardOptionsTests)
class RadiobuttonTest(AbstractLabelTest, unittest.TestCase): class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'activebackground', 'activeforeground', 'anchor', 'activebackground', 'activeforeground', 'anchor',
@ -264,7 +286,7 @@ class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
self.checkParams(widget, 'value', 1, 2.3, '', 'any string') self.checkParams(widget, 'value', 1, 2.3, '', 'any string')
@add_standard_options(StandardOptionsTests) @add_configure_tests(StandardOptionsTests)
class MenubuttonTest(AbstractLabelTest, unittest.TestCase): class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'activebackground', 'activeforeground', 'anchor', 'activebackground', 'activeforeground', 'anchor',
@ -277,10 +299,11 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
'takefocus', 'text', 'textvariable', 'takefocus', 'text', 'textvariable',
'underline', 'width', 'wraplength', 'underline', 'width', 'wraplength',
) )
_conv_pixels = round _rounds_pixels = (tk_version < (9, 0))
_clip_highlightthickness = True if tk_version < (9, 0):
_clip_pad = True _clipped = {'highlightthickness', 'padx', 'pady'}
_clip_borderwidth = False else:
_clipped ={ 'insertborderwidth', 'highlightthickness', 'padx', 'pady'}
def create(self, **kwargs): def create(self, **kwargs):
return tkinter.Menubutton(self.root, **kwargs) return tkinter.Menubutton(self.root, **kwargs)
@ -298,7 +321,10 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
widget = self.create() widget = self.create()
image = tkinter.PhotoImage(master=self.root, name='image1') image = tkinter.PhotoImage(master=self.root, name='image1')
self.checkParam(widget, 'image', image, conv=str) self.checkParam(widget, 'image', image, conv=str)
errmsg = 'image "spam" doesn\'t exist' if tk_version < (9, 0):
errmsg = 'image "spam" doesn\'t exist'
else:
errmsg = 'image "spam" does not exist'
with self.assertRaises(tkinter.TclError) as cm: with self.assertRaises(tkinter.TclError) as cm:
widget['image'] = 'spam' widget['image'] = 'spam'
if errmsg is not None: if errmsg is not None:
@ -328,9 +354,15 @@ class OptionMenuTest(MenubuttonTest, unittest.TestCase):
with self.assertRaisesRegex(TclError, r"^unknown option -image$"): with self.assertRaisesRegex(TclError, r"^unknown option -image$"):
tkinter.OptionMenu(self.root, None, 'b', image='') tkinter.OptionMenu(self.root, None, 'b', image='')
@add_configure_tests(IntegerSizeTests, StandardOptionsTests)
@add_standard_options(IntegerSizeTests, StandardOptionsTests)
class EntryTest(AbstractWidgetTest, unittest.TestCase): class EntryTest(AbstractWidgetTest, unittest.TestCase):
_rounds_pixels = (tk_version < (9, 0))
if tk_version < (9, 0):
_clipped = {'highlightthickness'}
else:
_clipped = {'highlightthickness', 'borderwidth', 'insertborderwidth',
'selectborderwidth'}
OPTIONS = ( OPTIONS = (
'background', 'borderwidth', 'cursor', 'background', 'borderwidth', 'cursor',
'disabledbackground', 'disabledforeground', 'disabledbackground', 'disabledforeground',
@ -355,16 +387,23 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
def test_configure_insertborderwidth(self): def test_configure_insertborderwidth(self):
widget = self.create(insertwidth=100) widget = self.create(insertwidth=100)
self.checkPixelsParam(widget, 'insertborderwidth', self.checkPixelsParam(widget, 'insertborderwidth',
0, 1.3, 2.6, 6, -2, '10p') 0, 1.3, 2.6, 6, '10p')
self.checkParam(widget, 'insertborderwidth', -2)
# insertborderwidth is bounded above by a half of insertwidth. # insertborderwidth is bounded above by a half of insertwidth.
self.checkParam(widget, 'insertborderwidth', 60, expected=100//2) expected = 100 // 2 if tk_version < (9, 0) else 60
self.checkParam(widget, 'insertborderwidth', 60, expected=expected)
def test_configure_insertwidth(self): def test_configure_insertwidth(self):
widget = self.create() widget = self.create()
self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, '10p') self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, '10p')
self.checkParam(widget, 'insertwidth', 0.1, expected=2) if tk_version < (9, 0):
self.checkParam(widget, 'insertwidth', -2, expected=2) self.checkParam(widget, 'insertwidth', 0.1, expected=2)
self.checkParam(widget, 'insertwidth', 0.9, expected=1) 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)
def test_configure_invalidcommand(self): def test_configure_invalidcommand(self):
widget = self.create() widget = self.create()
@ -422,7 +461,7 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
widget.selection_adjust(0) widget.selection_adjust(0)
@add_standard_options(StandardOptionsTests) @add_configure_tests(StandardOptionsTests)
class SpinboxTest(EntryTest, unittest.TestCase): class SpinboxTest(EntryTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'activebackground', 'background', 'borderwidth', 'activebackground', 'background', 'borderwidth',
@ -559,7 +598,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
self.assertEqual(widget.selection_element(), "buttondown") self.assertEqual(widget.selection_element(), "buttondown")
@add_standard_options(StandardOptionsTests) @add_configure_tests(StandardOptionsTests)
class TextTest(AbstractWidgetTest, unittest.TestCase): class TextTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'autoseparators', 'background', 'blockcursor', 'borderwidth', 'autoseparators', 'background', 'blockcursor', 'borderwidth',
@ -574,6 +613,9 @@ class TextTest(AbstractWidgetTest, unittest.TestCase):
'tabs', 'tabstyle', 'takefocus', 'undo', 'width', 'wrap', 'tabs', 'tabstyle', 'takefocus', 'undo', 'width', 'wrap',
'xscrollcommand', 'yscrollcommand', 'xscrollcommand', 'yscrollcommand',
) )
_rounds_pixels = (tk_version < (9, 0))
_no_round = {'selectborderwidth'}
_clipped = {'highlightthickness'}
def create(self, **kwargs): def create(self, **kwargs):
return tkinter.Text(self.root, **kwargs) return tkinter.Text(self.root, **kwargs)
@ -602,8 +644,10 @@ class TextTest(AbstractWidgetTest, unittest.TestCase):
def test_configure_height(self): def test_configure_height(self):
widget = self.create() widget = self.create()
self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, '3c') self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, '3c')
self.checkParam(widget, 'height', -100, expected=1) self.checkParam(widget, 'height', -100,
self.checkParam(widget, 'height', 0, expected=1) expected=1 if tk_version < (9, 0) else -100)
self.checkParam(widget, 'height', 0,
expected=1 if tk_version < (9, 0) else 0 )
def test_configure_maxundo(self): def test_configure_maxundo(self):
widget = self.create() widget = self.create()
@ -696,7 +740,7 @@ class TextTest(AbstractWidgetTest, unittest.TestCase):
self.assertRaises(TypeError, widget.bbox, '1.1', 'end') self.assertRaises(TypeError, widget.bbox, '1.1', 'end')
@add_standard_options(PixelSizeTests, StandardOptionsTests) @add_configure_tests(PixelSizeTests, StandardOptionsTests)
class CanvasTest(AbstractWidgetTest, unittest.TestCase): class CanvasTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'background', 'borderwidth', 'background', 'borderwidth',
@ -710,8 +754,15 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase):
'xscrollcommand', 'xscrollincrement', 'xscrollcommand', 'xscrollincrement',
'yscrollcommand', 'yscrollincrement', 'width', 'yscrollcommand', 'yscrollincrement', 'width',
) )
_rounds_pixels = True
_conv_pixels = round if tk_version < (9, 0):
_noround = {}
_clipped = {'highlightthickness'}
else:
_no_round = {'borderwidth', 'height', 'highlightthickness', 'width',
'xscrollincrement', 'yscrollincrement'}
_clipped = {'borderwidth', 'height', 'highlightthickness', 'width',
'xscrollincrement', 'yscrollincrement'}
_stringify = True _stringify = True
def create(self, **kwargs): def create(self, **kwargs):
@ -953,7 +1004,7 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase):
self.assertEqual(y2_2 - y1_2, y2_3 - y1_3) self.assertEqual(y2_2 - y1_2, y2_3 - y1_3)
@add_standard_options(IntegerSizeTests, StandardOptionsTests) @add_configure_tests(IntegerSizeTests, StandardOptionsTests)
class ListboxTest(AbstractWidgetTest, unittest.TestCase): class ListboxTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'activestyle', 'background', 'borderwidth', 'cursor', 'activestyle', 'background', 'borderwidth', 'cursor',
@ -965,6 +1016,11 @@ class ListboxTest(AbstractWidgetTest, unittest.TestCase):
'selectmode', 'setgrid', 'state', 'selectmode', 'setgrid', 'state',
'takefocus', 'width', 'xscrollcommand', 'yscrollcommand', 'takefocus', 'width', 'xscrollcommand', 'yscrollcommand',
) )
_rounds_pixels = (tk_version < (9, 0))
if tk_version < (9, 0):
_clipped = {'highlightthickness'}
else:
_clipped = { 'borderwidth', 'highlightthickness', 'selectborderwidth'}
def create(self, **kwargs): def create(self, **kwargs):
return tkinter.Listbox(self.root, **kwargs) return tkinter.Listbox(self.root, **kwargs)
@ -1091,7 +1147,7 @@ class ListboxTest(AbstractWidgetTest, unittest.TestCase):
self.assertRaises(TclError, lb.get, 2.4) self.assertRaises(TclError, lb.get, 2.4)
@add_standard_options(PixelSizeTests, StandardOptionsTests) @add_configure_tests(PixelSizeTests, StandardOptionsTests)
class ScaleTest(AbstractWidgetTest, unittest.TestCase): class ScaleTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'activebackground', 'background', 'bigincrement', 'borderwidth', 'activebackground', 'background', 'bigincrement', 'borderwidth',
@ -1102,6 +1158,8 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
'resolution', 'showvalue', 'sliderlength', 'sliderrelief', 'state', 'resolution', 'showvalue', 'sliderlength', 'sliderrelief', 'state',
'takefocus', 'tickinterval', 'to', 'troughcolor', 'variable', 'width', 'takefocus', 'tickinterval', 'to', 'troughcolor', 'variable', 'width',
) )
_rounds_pixels = (tk_version < (9, 0))
_clipped = {'highlightthickness'}
default_orient = 'vertical' default_orient = 'vertical'
def create(self, **kwargs): def create(self, **kwargs):
@ -1159,7 +1217,7 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
conv=float_round) conv=float_round)
@add_standard_options(PixelSizeTests, StandardOptionsTests) @add_configure_tests(PixelSizeTests, StandardOptionsTests)
class ScrollbarTest(AbstractWidgetTest, unittest.TestCase): class ScrollbarTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'activebackground', 'activerelief', 'activebackground', 'activerelief',
@ -1170,7 +1228,14 @@ class ScrollbarTest(AbstractWidgetTest, unittest.TestCase):
'repeatdelay', 'repeatinterval', 'repeatdelay', 'repeatinterval',
'takefocus', 'troughcolor', 'width', 'takefocus', 'troughcolor', 'width',
) )
_conv_pixels = round _rounds_pixels = True
if tk_version >= (9, 0):
_no_round = {'borderwidth', 'elementborderwidth', 'highlightthickness',
'width'}
if tk_version < (9, 0):
_clipped = {'highlightthickness'}
else:
_clipped = {'borderwidth', 'highlightthickness', 'width'}
_stringify = True _stringify = True
default_orient = 'vertical' default_orient = 'vertical'
@ -1208,7 +1273,7 @@ class ScrollbarTest(AbstractWidgetTest, unittest.TestCase):
self.assertRaises(TypeError, sb.set, 0.6, 0.7, 0.8) self.assertRaises(TypeError, sb.set, 0.6, 0.7, 0.8)
@add_standard_options(StandardOptionsTests) @add_configure_tests(StandardOptionsTests)
class PanedWindowTest(AbstractWidgetTest, unittest.TestCase): class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'background', 'borderwidth', 'cursor', 'background', 'borderwidth', 'cursor',
@ -1219,6 +1284,15 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
'sashcursor', 'sashpad', 'sashrelief', 'sashwidth', 'sashcursor', 'sashpad', 'sashrelief', 'sashwidth',
'showhandle', 'width', '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'}
_clipped = {}
default_orient = 'horizontal' default_orient = 'horizontal'
def create(self, **kwargs): def create(self, **kwargs):
@ -1347,13 +1421,13 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
def test_paneconfigure_padx(self): def test_paneconfigure_padx(self):
p, b, c = self.create2() p, b, c = self.create2()
self.check_paneconfigure(p, b, 'padx', 1.3, 1) self.check_paneconfigure(p, b, 'padx', 1.3, 1 if tk_version < (9, 0) else 1.3)
self.check_paneconfigure_bad(p, b, 'padx', self.check_paneconfigure_bad(p, b, 'padx',
EXPECTED_SCREEN_DISTANCE_ERRMSG.format('badValue')) EXPECTED_SCREEN_DISTANCE_ERRMSG.format('badValue'))
def test_paneconfigure_pady(self): def test_paneconfigure_pady(self):
p, b, c = self.create2() p, b, c = self.create2()
self.check_paneconfigure(p, b, 'pady', 1.3, 1) self.check_paneconfigure(p, b, 'pady', 1.3, 1 if tk_version < (9, 0) else 1.3)
self.check_paneconfigure_bad(p, b, 'pady', self.check_paneconfigure_bad(p, b, 'pady',
EXPECTED_SCREEN_DISTANCE_ERRMSG.format('badValue')) EXPECTED_SCREEN_DISTANCE_ERRMSG.format('badValue'))
@ -1379,17 +1453,17 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
EXPECTED_SCREEN_DISTANCE_OR_EMPTY_ERRMSG.format('badValue')) EXPECTED_SCREEN_DISTANCE_OR_EMPTY_ERRMSG.format('badValue'))
@add_standard_options(StandardOptionsTests) @add_configure_tests(StandardOptionsTests)
class MenuTest(AbstractWidgetTest, unittest.TestCase): class MenuTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'activebackground', 'activeborderwidth', 'activeforeground', 'activebackground', 'activeborderwidth', 'activeforeground',
'activerelief', 'activerelief', 'background', 'borderwidth', 'cursor',
'background', 'borderwidth', 'cursor',
'disabledforeground', 'font', 'foreground', 'disabledforeground', 'font', 'foreground',
'postcommand', 'relief', 'selectcolor', 'takefocus', 'postcommand', 'relief', 'selectcolor', 'takefocus',
'tearoff', 'tearoffcommand', 'title', 'type', 'tearoff', 'tearoffcommand', 'title', 'type',
) )
_conv_pixels = False _rounds_pixels = False
_clipped = {}
def create(self, **kwargs): def create(self, **kwargs):
return tkinter.Menu(self.root, **kwargs) return tkinter.Menu(self.root, **kwargs)
@ -1458,7 +1532,7 @@ class MenuTest(AbstractWidgetTest, unittest.TestCase):
self.assertEqual(str(m1.entrycget(1, 'variable')), str(v2)) self.assertEqual(str(m1.entrycget(1, 'variable')), str(v2))
@add_standard_options(PixelSizeTests, StandardOptionsTests) @add_configure_tests(PixelSizeTests, StandardOptionsTests)
class MessageTest(AbstractWidgetTest, unittest.TestCase): class MessageTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'anchor', 'aspect', 'background', 'borderwidth', 'anchor', 'aspect', 'background', 'borderwidth',
@ -1467,11 +1541,12 @@ class MessageTest(AbstractWidgetTest, unittest.TestCase):
'justify', 'padx', 'pady', 'relief', 'justify', 'padx', 'pady', 'relief',
'takefocus', 'text', 'textvariable', 'width', 'takefocus', 'text', 'textvariable', 'width',
) )
_conv_pad_pixels = False _rounds_pixels = (tk_version < (9, 0))
if tk_version >= (8, 7): _no_round = {'padx', 'pady'}
_conv_pixels = False if tk_version < (9, 0):
_clip_pad = tk_version >= (8, 7) _clipped = {'highlightthickness'}
_clip_borderwidth = tk_version >= (8, 7) else:
_clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady'}
def create(self, **kwargs): def create(self, **kwargs):
return tkinter.Message(self.root, **kwargs) return tkinter.Message(self.root, **kwargs)
@ -1482,16 +1557,14 @@ class MessageTest(AbstractWidgetTest, unittest.TestCase):
def test_configure_padx(self): def test_configure_padx(self):
widget = self.create() widget = self.create()
self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m', self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m')
conv=self._conv_pad_pixels) expected = -2 if tk_version < (9, 0) else self._default_pixels
expected = self._default_pixels if self._clip_pad else -2
self.checkParam(widget, 'padx', -2, expected=expected) self.checkParam(widget, 'padx', -2, expected=expected)
def test_configure_pady(self): def test_configure_pady(self):
widget = self.create() widget = self.create()
self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m', self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m')
conv=self._conv_pad_pixels) expected = -2 if tk_version < (9, 0) else self._default_pixels
expected = self._default_pixels if self._clip_pad else -2
self.checkParam(widget, 'pady', -2, expected=expected) self.checkParam(widget, 'pady', -2, expected=expected)
def test_configure_width(self): def test_configure_width(self):

View File

@ -6,17 +6,16 @@ from test.test_tkinter.support import (AbstractTkTest, requires_tk, tk_version,
pixels_conv, tcl_obj_eq) pixels_conv, tcl_obj_eq)
import test.support import test.support
_sentinel = object() _sentinel = object()
# Options which accept all values allowed by Tk_GetPixels
# borderwidth = bd
class AbstractWidgetTest(AbstractTkTest): class AbstractWidgetTest(AbstractTkTest):
_default_pixels = '' if tk_version >= (9, 0) else -1 if tk_version >= (8, 7) else '' _default_pixels = '' # Value for unset pixel options.
_conv_pixels = round _rounds_pixels = True # True if some pixel options are rounded.
_conv_pad_pixels = None _no_round = {} # Pixel options which are not rounded nonetheless
_stringify = False _stringify = False # Whether to convert tuples to strings
_clip_highlightthickness = True
_clip_pad = False
_clip_borderwidth = False
_allow_empty_justify = False _allow_empty_justify = False
@property @property
@ -44,6 +43,9 @@ class AbstractWidgetTest(AbstractTkTest):
widget[name] = value widget[name] = value
if expected is _sentinel: if expected is _sentinel:
expected = value expected = value
if name in self._clipped:
if not isinstance(expected, str):
expected = max(expected, 0)
if conv: if conv:
expected = conv(expected) expected = conv(expected)
if self._stringify or not self.wantobjects: if self._stringify or not self.wantobjects:
@ -140,14 +142,17 @@ class AbstractWidgetTest(AbstractTkTest):
errmsg = 'bad' + errmsg2 errmsg = 'bad' + errmsg2
self.checkInvalidParam(widget, name, 'spam', errmsg=errmsg) self.checkInvalidParam(widget, name, 'spam', errmsg=errmsg)
def checkPixelsParam(self, widget, name, *values, def checkPixelsParam(self, widget, name, *values, conv=None, **kwargs):
conv=None, **kwargs): if not self._rounds_pixels or name in self._no_round:
if conv is None: conv = False
conv = self._conv_pixels elif conv != str:
conv = round
for value in values: for value in values:
expected = _sentinel expected = _sentinel
conv1 = conv conv1 = conv
if isinstance(value, str): if isinstance(value, str):
if not getattr(self, '_converts_pixels', True):
conv1 = str
if conv1 and conv1 is not str: if conv1 and conv1 is not str:
expected = pixels_conv(value) * self.scaling expected = pixels_conv(value) * self.scaling
conv1 = round conv1 = round
@ -172,8 +177,12 @@ class AbstractWidgetTest(AbstractTkTest):
def checkImageParam(self, widget, name): def checkImageParam(self, widget, name):
image = tkinter.PhotoImage(master=self.root, name='image1') image = tkinter.PhotoImage(master=self.root, name='image1')
self.checkParam(widget, name, image, conv=str) self.checkParam(widget, name, image, conv=str)
if tk_version < (9, 0):
errmsg = 'image "spam" doesn\'t exist'
else:
errmsg = 'image "spam" does not exist'
self.checkInvalidParam(widget, name, 'spam', self.checkInvalidParam(widget, name, 'spam',
errmsg='image "spam" doesn\'t exist') errmsg=errmsg)
widget[name] = '' widget[name] = ''
def checkVariableParam(self, widget, name, var): def checkVariableParam(self, widget, name, var):
@ -215,31 +224,80 @@ class AbstractWidgetTest(AbstractTkTest):
print('%s.OPTIONS doesn\'t contain "%s"' % print('%s.OPTIONS doesn\'t contain "%s"' %
(self.__class__.__name__, k)) (self.__class__.__name__, k))
class PixelOptionsTests:
"""Standard options that accept all formats acceptable to Tk_GetPixels.
class StandardOptionsTests: In addition to numbers, these options can be set with distances
STANDARD_OPTIONS = ( specified as a string consisting of a number followed by a single
'activebackground', 'activeborderwidth', 'activeforeground', 'anchor', character giving the unit of distance. The allowed units are:
'background', 'bitmap', 'borderwidth', 'compound', 'cursor', millimeters ('m'), centimeters ('c'), inches ('i') or points ('p').
'disabledforeground', 'exportselection', 'font', 'foreground', In Tk 9 a cget call for one of these options returns a Tcl_Obj of
'highlightbackground', 'highlightcolor', 'highlightthickness', type "pixels", whose string representation is the distance string
'image', 'insertbackground', 'insertborderwidth', passed to configure.
'insertofftime', 'insertontime', 'insertwidth', """
'jump', 'justify', 'orient', 'padx', 'pady', 'relief', PIXEL_OPTIONS = ('activeborderwidth', 'borderwidth', 'highlightthickness',
'repeatdelay', 'repeatinterval', 'insertborderwidth', 'insertwidth', 'padx', 'pady', 'selectborderwidth')
'selectbackground', 'selectborderwidth', 'selectforeground',
'setgrid', 'takefocus', 'text', 'textvariable', 'troughcolor',
'underline', 'wraplength', 'xscrollcommand', 'yscrollcommand',
)
def test_configure_activebackground(self):
widget = self.create()
self.checkColorParam(widget, 'activebackground')
def test_configure_activeborderwidth(self): def test_configure_activeborderwidth(self):
widget = self.create() widget = self.create()
self.checkPixelsParam(widget, 'activeborderwidth', self.checkPixelsParam(widget, 'activeborderwidth',
0, 1.3, 2.9, 6, -2, '10p') 0, 1.3, 2.9, 6, -2, '10p')
def test_configure_borderwidth(self):
widget = self.create()
self.checkPixelsParam(widget, 'borderwidth',
0, 1.3, 2.6, 6, '10p')
self.checkParam(widget, 'borderwidth', -2)
if 'bd' in self.OPTIONS:
self.checkPixelsParam(widget, 'bd', 0, 1.3, 2.6, 6, '10p')
self.checkParam(widget, 'bd', -2, expected=expected)
def test_configure_highlightthickness(self):
widget = self.create()
self.checkPixelsParam(widget, 'highlightthickness',
0, 1.3, 2.6, 6, '10p')
self.checkParam(widget, 'highlightthickness', -2)
def test_configure_insertborderwidth(self):
widget = self.create()
self.checkPixelsParam(widget, 'insertborderwidth',
0, 1.3, 2.6, 6, '10p')
self.checkParam(widget, 'insertborderwidth', -2)
def test_configure_insertwidth(self):
widget = self.create()
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')
self.checkParam(widget, 'padx', -2)
def test_configure_pady(self):
widget = self.create()
self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m')
self.checkParam(widget, 'pady', -2)
def test_configure_selectborderwidth(self):
widget = self.create()
self.checkPixelsParam(widget, 'selectborderwidth', 1.3, 2.6, -2, '10p')
class StandardOptionsTests(PixelOptionsTests):
STANDARD_OPTIONS = ( 'activebackground', 'activeforeground',
'anchor', 'background', 'bitmap', 'compound', 'cursor',
'disabledforeground', 'exportselection', 'font', 'foreground',
'highlightbackground', 'highlightcolor', 'image',
'insertbackground', 'insertofftime', 'insertontime', 'jump',
'justify', 'orient', 'relief', 'repeatdelay', 'repeatinterval',
'selectbackground', 'selectforeground', 'setgrid', 'takefocus',
'text', 'textvariable', 'troughcolor', 'underline', 'wraplength',
'xscrollcommand', 'yscrollcommand', ) + PixelOptionsTests.PIXEL_OPTIONS
def test_configure_activebackground(self):
widget = self.create()
self.checkColorParam(widget, 'activebackground')
def test_configure_activeforeground(self): def test_configure_activeforeground(self):
widget = self.create() widget = self.create()
self.checkColorParam(widget, 'activeforeground') self.checkColorParam(widget, 'activeforeground')
@ -277,18 +335,6 @@ class StandardOptionsTests:
self.checkInvalidParam(widget, 'bitmap', 'spam', self.checkInvalidParam(widget, 'bitmap', 'spam',
errmsg='bitmap "spam" not defined') errmsg='bitmap "spam" not defined')
def test_configure_borderwidth(self):
widget = self.create()
self.checkPixelsParam(widget, 'borderwidth',
0, 1.3, 2.6, 6, '10p')
expected = 0 if self._clip_borderwidth else -2
self.checkParam(widget, 'borderwidth', -2, expected=expected,
conv=self._conv_pixels)
if 'bd' in self.OPTIONS:
self.checkPixelsParam(widget, 'bd', 0, 1.3, 2.6, 6, '10p')
self.checkParam(widget, 'bd', -2, expected=expected,
conv=self._conv_pixels)
def test_configure_compound(self): def test_configure_compound(self):
widget = self.create() widget = self.create()
self.checkEnumParam(widget, 'compound', self.checkEnumParam(widget, 'compound',
@ -312,8 +358,8 @@ class StandardOptionsTests:
'-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*') '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*')
is_ttk = widget.__class__.__module__ == 'tkinter.ttk' is_ttk = widget.__class__.__module__ == 'tkinter.ttk'
if not is_ttk: if not is_ttk:
self.checkInvalidParam(widget, 'font', '', errmsg = 'font "" does ?n[o\']t exist'
errmsg='font "" doesn\'t exist') self.checkInvalidParam(widget, 'font', '', errmsg=errmsg)
def test_configure_foreground(self): def test_configure_foreground(self):
widget = self.create() widget = self.create()
@ -329,14 +375,6 @@ class StandardOptionsTests:
widget = self.create() widget = self.create()
self.checkColorParam(widget, 'highlightcolor') self.checkColorParam(widget, 'highlightcolor')
def test_configure_highlightthickness(self):
widget = self.create()
self.checkPixelsParam(widget, 'highlightthickness',
0, 1.3, 2.6, 6, '10p')
expected = 0 if self._clip_highlightthickness else -2
self.checkParam(widget, 'highlightthickness', -2, expected=expected,
conv=self._conv_pixels)
def test_configure_image(self): def test_configure_image(self):
widget = self.create() widget = self.create()
self.checkImageParam(widget, 'image') self.checkImageParam(widget, 'image')
@ -345,11 +383,6 @@ class StandardOptionsTests:
widget = self.create() widget = self.create()
self.checkColorParam(widget, 'insertbackground') self.checkColorParam(widget, 'insertbackground')
def test_configure_insertborderwidth(self):
widget = self.create()
self.checkPixelsParam(widget, 'insertborderwidth',
0, 1.3, 2.6, 6, -2, '10p')
def test_configure_insertofftime(self): def test_configure_insertofftime(self):
widget = self.create() widget = self.create()
self.checkIntegerParam(widget, 'insertofftime', 100) self.checkIntegerParam(widget, 'insertofftime', 100)
@ -358,10 +391,6 @@ class StandardOptionsTests:
widget = self.create() widget = self.create()
self.checkIntegerParam(widget, 'insertontime', 100) self.checkIntegerParam(widget, 'insertontime', 100)
def test_configure_insertwidth(self):
widget = self.create()
self.checkPixelsParam(widget, 'insertwidth', 1.3, 2.6, -2, '10p')
def test_configure_jump(self): def test_configure_jump(self):
widget = self.create() widget = self.create()
self.checkBooleanParam(widget, 'jump') self.checkBooleanParam(widget, 'jump')
@ -379,22 +408,6 @@ class StandardOptionsTests:
self.assertEqual(str(widget['orient']), self.default_orient) self.assertEqual(str(widget['orient']), self.default_orient)
self.checkEnumParam(widget, 'orient', 'horizontal', 'vertical') self.checkEnumParam(widget, 'orient', 'horizontal', 'vertical')
def test_configure_padx(self):
widget = self.create()
self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m',
conv=self._conv_pad_pixels)
expected = 0 if self._clip_pad else -2
self.checkParam(widget, 'padx', -2, expected=expected,
conv=self._conv_pad_pixels)
def test_configure_pady(self):
widget = self.create()
self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m',
conv=self._conv_pad_pixels)
expected = 0 if self._clip_pad else -2
self.checkParam(widget, 'pady', -2, expected=expected,
conv=self._conv_pad_pixels)
@requires_tk(8, 7) @requires_tk(8, 7)
def test_configure_placeholder(self): def test_configure_placeholder(self):
widget = self.create() widget = self.create()
@ -421,10 +434,6 @@ class StandardOptionsTests:
widget = self.create() widget = self.create()
self.checkColorParam(widget, 'selectbackground') self.checkColorParam(widget, 'selectbackground')
def test_configure_selectborderwidth(self):
widget = self.create()
self.checkPixelsParam(widget, 'selectborderwidth', 1.3, 2.6, -2, '10p')
def test_configure_selectforeground(self): def test_configure_selectforeground(self):
widget = self.create() widget = self.create()
self.checkColorParam(widget, 'selectforeground') self.checkColorParam(widget, 'selectforeground')
@ -534,6 +543,7 @@ class StandardOptionsTests:
class IntegerSizeTests: class IntegerSizeTests:
""" Tests widgets which only accept integral width and height."""
def test_configure_height(self): def test_configure_height(self):
widget = self.create() widget = self.create()
self.checkIntegerParam(widget, 'height', 100, -100, 0) self.checkIntegerParam(widget, 'height', 100, -100, 0)
@ -544,6 +554,7 @@ class IntegerSizeTests:
class PixelSizeTests: class PixelSizeTests:
""" Tests widgets which accept screen distances for width and height."""
def test_configure_height(self): def test_configure_height(self):
widget = self.create() widget = self.create()
self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '3c') self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '3c')
@ -553,7 +564,7 @@ class PixelSizeTests:
self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i') self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i')
def add_standard_options(*source_classes): def add_configure_tests(*source_classes):
# This decorator adds test_configure_xxx methods from source classes for # This decorator adds test_configure_xxx methods from source classes for
# every xxx option in the OPTIONS class attribute if they are not defined # every xxx option in the OPTIONS class attribute if they are not defined
# explicitly. # explicitly.

View File

@ -205,7 +205,8 @@ class StyleTest(AbstractTkTest, unittest.TestCase):
style = self.style style = self.style
with self.assertRaises(IndexError): with self.assertRaises(IndexError):
style.element_create('plain.newelem', 'from') style.element_create('plain.newelem', 'from')
with self.assertRaisesRegex(TclError, 'theme "spam" doesn\'t exist'): with self.assertRaisesRegex(TclError,
'theme "spam" (does not|doesn\'t) exist'):
style.element_create('plain.newelem', 'from', 'spam') style.element_create('plain.newelem', 'from', 'spam')
def test_element_create_image(self): def test_element_create_image(self):

View File

@ -8,7 +8,7 @@ from test.test_ttk_textonly import MockTclObj
from test.test_tkinter.support import ( from test.test_tkinter.support import (
AbstractTkTest, requires_tk, tk_version, get_tk_patchlevel, AbstractTkTest, requires_tk, tk_version, get_tk_patchlevel,
simulate_mouse_click, AbstractDefaultRootTest) simulate_mouse_click, AbstractDefaultRootTest)
from test.test_tkinter.widget_tests import (add_standard_options, from test.test_tkinter.widget_tests import (add_configure_tests,
AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests) AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests)
requires('gui') requires('gui')
@ -125,10 +125,11 @@ class WidgetTest(AbstractTkTest, unittest.TestCase):
class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests): class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests):
_conv_pixels = False _rounds_pixels = False
_clipped = {}
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class FrameTest(AbstractToplevelTest, unittest.TestCase): class FrameTest(AbstractToplevelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'borderwidth', 'class', 'cursor', 'height', 'borderwidth', 'class', 'cursor', 'height',
@ -140,7 +141,7 @@ class FrameTest(AbstractToplevelTest, unittest.TestCase):
return ttk.Frame(self.root, **kwargs) return ttk.Frame(self.root, **kwargs)
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class LabelFrameTest(AbstractToplevelTest, unittest.TestCase): class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'borderwidth', 'class', 'cursor', 'height', 'borderwidth', 'class', 'cursor', 'height',
@ -168,6 +169,8 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
class AbstractLabelTest(AbstractWidgetTest): class AbstractLabelTest(AbstractWidgetTest):
_allow_empty_justify = True _allow_empty_justify = True
_rounds_pixels = False
_clipped = {}
def checkImageParam(self, widget, name): def checkImageParam(self, widget, name):
image = tkinter.PhotoImage(master=self.root, name='image1') image = tkinter.PhotoImage(master=self.root, name='image1')
@ -179,8 +182,11 @@ class AbstractLabelTest(AbstractWidgetTest):
expected=('image1', 'active', 'image2')) expected=('image1', 'active', 'image2'))
self.checkParam(widget, name, 'image1 active image2', self.checkParam(widget, name, 'image1 active image2',
expected=('image1', 'active', 'image2')) expected=('image1', 'active', 'image2'))
self.checkInvalidParam(widget, name, 'spam', if tk_version < (9, 0):
errmsg='image "spam" doesn\'t exist') errmsg = 'image "spam" doesn\'t exist'
else:
errmsg = 'image "spam" does not exist'
self.checkInvalidParam(widget, name, 'spam', errmsg=errmsg)
def test_configure_compound(self): def test_configure_compound(self):
values = ('none', 'text', 'image', 'center', 'top', 'bottom', 'left', 'right') values = ('none', 'text', 'image', 'center', 'top', 'bottom', 'left', 'right')
@ -196,7 +202,7 @@ class AbstractLabelTest(AbstractWidgetTest):
self.checkParams(widget, 'width', 402, -402, 0) self.checkParams(widget, 'width', 402, -402, 0)
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class LabelTest(AbstractLabelTest, unittest.TestCase): class LabelTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'anchor', 'background', 'borderwidth', 'anchor', 'background', 'borderwidth',
@ -214,7 +220,7 @@ class LabelTest(AbstractLabelTest, unittest.TestCase):
test_configure_justify = StandardOptionsTests.test_configure_justify test_configure_justify = StandardOptionsTests.test_configure_justify
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class ButtonTest(AbstractLabelTest, unittest.TestCase): class ButtonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'class', 'command', 'compound', 'cursor', 'default', 'class', 'command', 'compound', 'cursor', 'default',
@ -239,7 +245,7 @@ class ButtonTest(AbstractLabelTest, unittest.TestCase):
self.assertTrue(success) self.assertTrue(success)
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class CheckbuttonTest(AbstractLabelTest, unittest.TestCase): class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'class', 'command', 'compound', 'cursor', 'class', 'command', 'compound', 'cursor',
@ -326,7 +332,7 @@ class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
self.assertEqual(len(set(variables)), len(buttons), variables) self.assertEqual(len(set(variables)), len(buttons), variables)
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) @add_configure_tests(IntegerSizeTests, StandardTtkOptionsTests)
class EntryTest(AbstractWidgetTest, unittest.TestCase): class EntryTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'background', 'class', 'cursor', 'background', 'class', 'cursor',
@ -336,6 +342,8 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
'show', 'state', 'style', 'takefocus', 'textvariable', 'show', 'state', 'style', 'takefocus', 'textvariable',
'validate', 'validatecommand', 'width', 'xscrollcommand', 'validate', 'validatecommand', 'width', 'xscrollcommand',
) )
_rounds_pixels = False
_clipped = {}
# bpo-27313: macOS Tk/Tcl may or may not report 'Entry.field'. # bpo-27313: macOS Tk/Tcl may or may not report 'Entry.field'.
IDENTIFY_AS = {'Entry.field', 'textarea'} IDENTIFY_AS = {'Entry.field', 'textarea'}
@ -371,8 +379,12 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
self.assertRaises(tkinter.TclError, self.entry.bbox, None) self.assertRaises(tkinter.TclError, self.entry.bbox, None)
def test_identify(self): def test_identify(self):
if (tk_version >= (9, 0) and sys.platform == 'darwin'
and isinstance(self.entry, ttk.Combobox)):
self.skipTest('Test does not work on macOS Tk 9.')
# https://core.tcl-lang.org/tk/tktview/8b49e9cfa6
self.entry.pack() self.entry.pack()
self.entry.update() self.root.update()
self.assertIn(self.entry.identify(5, 5), self.IDENTIFY_AS) self.assertIn(self.entry.identify(5, 5), self.IDENTIFY_AS)
self.assertEqual(self.entry.identify(-1, -1), "") self.assertEqual(self.entry.identify(-1, -1), "")
@ -450,7 +462,7 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
self.assertEqual(self.entry.state(), ()) self.assertEqual(self.entry.state(), ())
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) @add_configure_tests(IntegerSizeTests, StandardTtkOptionsTests)
class ComboboxTest(EntryTest, unittest.TestCase): class ComboboxTest(EntryTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'background', 'class', 'cursor', 'exportselection', 'background', 'class', 'cursor', 'exportselection',
@ -479,11 +491,14 @@ class ComboboxTest(EntryTest, unittest.TestCase):
x, y = width - 5, 5 x, y = width - 5, 5
if sys.platform != 'darwin': # there's no down arrow on macOS if sys.platform != 'darwin': # there's no down arrow on macOS
self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z') self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z')
self.combo.event_generate('<ButtonPress-1>', x=x, y=y) self.combo.event_generate('<Button-1>', x=x, y=y)
self.combo.event_generate('<ButtonRelease-1>', x=x, y=y) self.combo.event_generate('<ButtonRelease-1>', x=x, y=y)
self.combo.update_idletasks()
def test_virtual_event(self): def test_virtual_event(self):
if (tk_version >= (9, 0) and sys.platform == 'darwin'
and isinstance(self.entry, ttk.Combobox)):
self.skipTest('Test does not work on macOS Tk 9.')
# https://core.tcl-lang.org/tk/tktview/8b49e9cfa6
success = [] success = []
self.combo['values'] = [1] self.combo['values'] = [1]
@ -501,6 +516,10 @@ class ComboboxTest(EntryTest, unittest.TestCase):
self.assertTrue(success) self.assertTrue(success)
def test_configure_postcommand(self): def test_configure_postcommand(self):
if (tk_version >= (9, 0) and sys.platform == 'darwin'
and isinstance(self.entry, ttk.Combobox)):
self.skipTest('Test does not work on macOS Tk 9.')
# https://core.tcl-lang.org/tk/tktview/8b49e9cfa6
success = [] success = []
self.combo['postcommand'] = lambda: success.append(True) self.combo['postcommand'] = lambda: success.append(True)
@ -576,12 +595,14 @@ class ComboboxTest(EntryTest, unittest.TestCase):
combo2.destroy() combo2.destroy()
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) @add_configure_tests(IntegerSizeTests, StandardTtkOptionsTests)
class PanedWindowTest(AbstractWidgetTest, unittest.TestCase): class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'class', 'cursor', 'height', 'class', 'cursor', 'height',
'orient', 'style', 'takefocus', 'width', 'orient', 'style', 'takefocus', 'width',
) )
_rounds_pixels = False
_clipped = {}
def setUp(self): def setUp(self):
super().setUp() super().setUp()
@ -712,7 +733,7 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
self.assertIsInstance(self.paned.sashpos(0), int) self.assertIsInstance(self.paned.sashpos(0), int)
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class RadiobuttonTest(AbstractLabelTest, unittest.TestCase): class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'class', 'command', 'compound', 'cursor', 'class', 'command', 'compound', 'cursor',
@ -791,13 +812,14 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
menu.destroy() menu.destroy()
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class ScaleTest(AbstractWidgetTest, unittest.TestCase): class ScaleTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'class', 'command', 'cursor', 'from', 'length', 'class', 'command', 'cursor', 'from', 'length',
'orient', 'state', 'style', 'takefocus', 'to', 'value', 'variable', 'orient', 'state', 'style', 'takefocus', 'to', 'value', 'variable',
) )
_conv_pixels = False _rounds_pixels = False
_clipped = {}
default_orient = 'horizontal' default_orient = 'horizontal'
def setUp(self): def setUp(self):
@ -899,7 +921,7 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
self.assertRaises(tkinter.TclError, self.scale.set, None) self.assertRaises(tkinter.TclError, self.scale.set, None)
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class ProgressbarTest(AbstractWidgetTest, unittest.TestCase): class ProgressbarTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'anchor', 'class', 'cursor', 'font', 'foreground', 'justify', 'anchor', 'class', 'cursor', 'font', 'foreground', 'justify',
@ -907,7 +929,8 @@ class ProgressbarTest(AbstractWidgetTest, unittest.TestCase):
'mode', 'maximum', 'phase', 'text', 'wraplength', 'mode', 'maximum', 'phase', 'text', 'wraplength',
'style', 'takefocus', 'value', 'variable', 'style', 'takefocus', 'value', 'variable',
) )
_conv_pixels = False _rounds_pixels = False
_clipped = {}
_allow_empty_justify = True _allow_empty_justify = True
default_orient = 'horizontal' default_orient = 'horizontal'
@ -952,24 +975,27 @@ class ProgressbarTest(AbstractWidgetTest, unittest.TestCase):
@unittest.skipIf(sys.platform == 'darwin', @unittest.skipIf(sys.platform == 'darwin',
'ttk.Scrollbar is special on MacOSX') 'ttk.Scrollbar is special on MacOSX')
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class ScrollbarTest(AbstractWidgetTest, unittest.TestCase): class ScrollbarTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'class', 'command', 'cursor', 'orient', 'style', 'takefocus', 'class', 'command', 'cursor', 'orient', 'style', 'takefocus',
) )
_rounds_pixels = False
_clipped = {}
default_orient = 'vertical' default_orient = 'vertical'
def create(self, **kwargs): def create(self, **kwargs):
return ttk.Scrollbar(self.root, **kwargs) return ttk.Scrollbar(self.root, **kwargs)
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class NotebookTest(AbstractWidgetTest, unittest.TestCase): class NotebookTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'class', 'cursor', 'height', 'padding', 'style', 'takefocus', 'width', 'class', 'cursor', 'height', 'padding', 'style', 'takefocus', 'width',
) )
if tk_version >= (8, 7): _rounds_pixels = (tk_version < (9,0))
_conv_pixels = False _converts_pixels = False
_clipped = {}
def setUp(self): def setUp(self):
super().setUp() super().setUp()
@ -987,14 +1013,14 @@ class NotebookTest(AbstractWidgetTest, unittest.TestCase):
if get_tk_patchlevel(self.root) < (8, 6, 15): if get_tk_patchlevel(self.root) < (8, 6, 15):
self.checkIntegerParam(widget, 'height', 402, -402, 0) self.checkIntegerParam(widget, 'height', 402, -402, 0)
else: else:
self.checkPixelsParam(widget, 'height', '10c', 402, -402, 0, conv=False) self.checkPixelsParam(widget, 'height', '10c', 402, -402, 0)
def test_configure_width(self): def test_configure_width(self):
widget = self.create() widget = self.create()
if get_tk_patchlevel(self.root) < (8, 6, 15): if get_tk_patchlevel(self.root) < (8, 6, 15):
self.checkIntegerParam(widget, 'width', 402, -402, 0) self.checkIntegerParam(widget, 'width', 402, -402, 0)
else: else:
self.checkPixelsParam(widget, 'width', '10c', 402, -402, 0, conv=False) self.checkPixelsParam(widget, 'width', '10c', 402, -402, 0)
def test_tab_identifiers(self): def test_tab_identifiers(self):
self.nb.forget(0) self.nb.forget(0)
@ -1160,7 +1186,12 @@ class NotebookTest(AbstractWidgetTest, unittest.TestCase):
self.nb.select(0) self.nb.select(0)
focus_identify_as = 'focus' if sys.platform != 'darwin' else '' if sys.platform == 'darwin':
focus_identify_as = ''
elif sys.platform == 'win32':
focus_identify_as = 'focus'
else:
focus_identify_as = 'focus' if tk_version < (9,0) else 'padding'
self.assertEqual(self.nb.identify(5, 5), focus_identify_as) self.assertEqual(self.nb.identify(5, 5), focus_identify_as)
simulate_mouse_click(self.nb, 5, 5) simulate_mouse_click(self.nb, 5, 5)
self.nb.focus_force() self.nb.focus_force()
@ -1193,7 +1224,7 @@ class NotebookTest(AbstractWidgetTest, unittest.TestCase):
self.assertEqual(self.nb.select(), str(self.child2)) self.assertEqual(self.nb.select(), str(self.child2))
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) @add_configure_tests(IntegerSizeTests, StandardTtkOptionsTests)
class SpinboxTest(EntryTest, unittest.TestCase): class SpinboxTest(EntryTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'background', 'class', 'command', 'cursor', 'exportselection', 'background', 'class', 'command', 'cursor', 'exportselection',
@ -1370,7 +1401,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
spin2.destroy() spin2.destroy()
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class TreeviewTest(AbstractWidgetTest, unittest.TestCase): class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'class', 'columns', 'cursor', 'displaycolumns', 'class', 'columns', 'cursor', 'displaycolumns',
@ -1378,6 +1409,8 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
'style', 'takefocus', 'titlecolumns', 'titleitems', 'style', 'takefocus', 'titlecolumns', 'titleitems',
'xscrollcommand', 'yscrollcommand', 'xscrollcommand', 'yscrollcommand',
) )
_rounds_pixels = False
_clipped = {}
def setUp(self): def setUp(self):
super().setUp() super().setUp()
@ -1413,8 +1446,10 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
def test_configure_height(self): def test_configure_height(self):
widget = self.create() widget = self.create()
self.checkPixelsParam(widget, 'height', 100, -100, 0, '3c', conv=False) self.checkPixelsParam(widget, 'height', 100, -100, 0, '3c',
self.checkPixelsParam(widget, 'height', 101.2, 102.6, conv=False) conv=False)
self.checkPixelsParam(widget, 'height', 101.2, 102.6, '3c',
conv=False)
def test_configure_selectmode(self): def test_configure_selectmode(self):
widget = self.create() widget = self.create()
@ -1936,24 +1971,28 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
self.assertEqual(self.tv.tag_has('tag3'), ()) self.assertEqual(self.tv.tag_has('tag3'), ())
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class SeparatorTest(AbstractWidgetTest, unittest.TestCase): class SeparatorTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'class', 'cursor', 'orient', 'style', 'takefocus', 'class', 'cursor', 'orient', 'style', 'takefocus',
# 'state'? # 'state'?
) )
_rounds_pixels = False
_clipped = {}
default_orient = 'horizontal' default_orient = 'horizontal'
def create(self, **kwargs): def create(self, **kwargs):
return ttk.Separator(self.root, **kwargs) return ttk.Separator(self.root, **kwargs)
@add_standard_options(StandardTtkOptionsTests) @add_configure_tests(StandardTtkOptionsTests)
class SizegripTest(AbstractWidgetTest, unittest.TestCase): class SizegripTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = ( OPTIONS = (
'class', 'cursor', 'style', 'takefocus', 'class', 'cursor', 'style', 'takefocus',
# 'state'? # 'state'?
) )
_rounds_pixels = False
_clipped = {}
def create(self, **kwargs): def create(self, **kwargs):
return ttk.Sizegrip(self.root, **kwargs) return ttk.Sizegrip(self.root, **kwargs)

View File

@ -321,6 +321,8 @@ def _tclobj_to_py(val):
elif hasattr(val, 'typename'): # some other (single) Tcl object elif hasattr(val, 'typename'): # some other (single) Tcl object
val = _convert_stringval(val) val = _convert_stringval(val)
if isinstance(val, tuple) and len(val) == 0:
return ''
return val return val
def tclobjs_to_py(adict): def tclobjs_to_py(adict):

View File

@ -0,0 +1,4 @@
The tkinter module can now be built to use either the new version 9.0.0 of
Tcl/Tk or the latest release 8.6.15 of Tcl/Tk 8. Tcl/Tk 9 includes many
improvements, both to the Tcl language and to the appearance and utility of
the graphical user interface provided by Tk.

View File

@ -325,6 +325,7 @@ typedef struct {
const Tcl_ObjType *ListType; const Tcl_ObjType *ListType;
const Tcl_ObjType *StringType; const Tcl_ObjType *StringType;
const Tcl_ObjType *UTF32StringType; const Tcl_ObjType *UTF32StringType;
const Tcl_ObjType *PixelType;
} TkappObject; } TkappObject;
#define Tkapp_Interp(v) (((TkappObject *) (v))->interp) #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
@ -637,6 +638,7 @@ Tkapp_New(const char *screenName, const char *className,
v->ListType = Tcl_GetObjType("list"); v->ListType = Tcl_GetObjType("list");
v->StringType = Tcl_GetObjType("string"); v->StringType = Tcl_GetObjType("string");
v->UTF32StringType = Tcl_GetObjType("utf32string"); v->UTF32StringType = Tcl_GetObjType("utf32string");
v->PixelType = Tcl_GetObjType("pixel");
/* Delete the 'exit' command, which can screw things up */ /* Delete the 'exit' command, which can screw things up */
Tcl_DeleteCommand(v->interp, "exit"); Tcl_DeleteCommand(v->interp, "exit");
@ -1236,7 +1238,8 @@ FromObj(TkappObject *tkapp, Tcl_Obj *value)
} }
if (value->typePtr == tkapp->StringType || if (value->typePtr == tkapp->StringType ||
value->typePtr == tkapp->UTF32StringType) value->typePtr == tkapp->UTF32StringType ||
value->typePtr == tkapp->PixelType)
{ {
return unicodeFromTclObj(tkapp, value); return unicodeFromTclObj(tkapp, value);
} }

View File

@ -94,6 +94,7 @@
<ItemDefinitionGroup> <ItemDefinitionGroup>
<ClCompile> <ClCompile>
<AdditionalIncludeDirectories>$(tcltkDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(tcltkDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="$(TclMajorVersion) == '9'">TCL_WITH_EXTERNAL_TOMMATH;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WITH_APPINIT;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WITH_APPINIT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(BuildForRelease)' != 'true'">Py_TCLTK_DIR="$(tcltkDir.TrimEnd('\').Replace('\', '\\'))";%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'$(BuildForRelease)' != 'true'">Py_TCLTK_DIR="$(tcltkDir.TrimEnd('\').Replace('\', '\\'))";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
@ -109,9 +110,10 @@
<ResourceCompile Include="..\PC\python_nt.rc" /> <ResourceCompile Include="..\PC\python_nt.rc" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<_TclTkDLL Include="$(tcltkdir)\bin\$(tclDllName)" /> <_TclTkDLL Include="$(tcltkdir)\bin\$(tclDLLName)" />
<_TclTkDLL Include="$(tcltkdir)\bin\$(tkDllName)" /> <_TclTkDLL Include="$(tcltkdir)\bin\$(tkDLLName)" />
<_TclTkDLL Include="$(tcltkdir)\bin\$(tclZlibDllName)" /> <_TclTkDLL Include="$(tcltkdir)\bin\$(tclZlibDLLName)" />
<_TclTkDLL Include="$(tcltkdir)\bin\$(tommathDLLName)" Condition="$(tommathDLLName) != ''"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj"> <ProjectReference Include="pythoncore.vcxproj">

View File

@ -11,7 +11,7 @@ echo.directly to MSBuild may be passed. If the argument contains an '=', the
echo.entire argument must be quoted (e.g. `%~nx0 "/p:PlatformToolset=v141"`). echo.entire argument must be quoted (e.g. `%~nx0 "/p:PlatformToolset=v141"`).
echo.Alternatively you can put extra flags for MSBuild in a file named echo.Alternatively you can put extra flags for MSBuild in a file named
echo.`msbuild.rsp` in the `PCbuild` directory, one flag per line. This file echo.`msbuild.rsp` in the `PCbuild` directory, one flag per line. This file
echo.will be picked automatically by MSBuild. Flags put in this file does not echo.will be picked automatically by MSBuild. Flags put in this file do not
echo.need to be quoted. You can still use environment variables inside the echo.need to be quoted. You can still use environment variables inside the
echo.response file. echo.response file.
echo. echo.

View File

@ -17,15 +17,21 @@
<tcltkDir Condition="$(tcltkDir) == ''">$(ExternalsDir)tcltk-$(TclVersion)\$(ArchName)\</tcltkDir> <tcltkDir Condition="$(tcltkDir) == ''">$(ExternalsDir)tcltk-$(TclVersion)\$(ArchName)\</tcltkDir>
<tclWin32Exe Condition="$(Platform) == 'Win32'">$(tcltkDir)\bin\tclsh$(TclMajorVersion)$(TclMinorVersion)t.exe</tclWin32Exe> <tclWin32Exe Condition="$(Platform) == 'Win32'">$(tcltkDir)\bin\tclsh$(TclMajorVersion)$(TclMinorVersion)t.exe</tclWin32Exe>
<tclWin32Exe Condition="$(Platform) != 'Win32'">$(tcltkDir)\..\win32\bin\tclsh$(TclMajorVersion)$(TclMinorVersion)t.exe</tclWin32Exe> <tclWin32Exe Condition="$(Platform) != 'Win32'">$(tcltkDir)\..\win32\bin\tclsh$(TclMajorVersion)$(TclMinorVersion)t.exe</tclWin32Exe>
<tclExternalTommath Condition="$(TclMajorVersion) == '9'">TCL_WITH_EXTERNAL_TOMMATH;</tclExternalTommath>
<!--<TclDebugExt Condition="'$(Configuration)' == 'Debug'">g</TclDebugExt>--> <!--<TclDebugExt Condition="'$(Configuration)' == 'Debug'">g</TclDebugExt>-->
<tclDLLName>tcl$(TclMajorVersion)$(TclMinorVersion)t$(TclDebugExt).dll</tclDLLName> <tcltkSuffix Condition="'$(TclMajorVersion)' == '8'">t</tcltkSuffix>
<tclLibName>tcl$(TclMajorVersion)$(TclMinorVersion)t$(TclDebugExt).lib</tclLibName> <tkPrefix Condition="'$(TclMajorVersion)' == '9'">tcl9</tkPrefix>
<tclShExeName>tclsh$(TclMajorVersion)$(TclMinorVersion)t$(TclDebugExt).exe</tclShExeName> <tclDLLName >tcl$(TclMajorVersion)$(TclMinorVersion)$(tcltkSuffix)$(TclDebugExt).dll</tclDLLName>
<tkDLLName>tk$(TkMajorVersion)$(TkMinorVersion)t$(TclDebugExt).dll</tkDLLName> <tclLibName>tcl$(TclMajorVersion)$(TclMinorVersion)$(tcltkSuffix)$(TclDebugExt).lib</tclLibName>
<tkLibName>tk$(TkMajorVersion)$(TkMinorVersion)t$(TclDebugExt).lib</tkLibName> <tclShExeName>tclsh$(TclMajorVersion)$(TclMinorVersion)$(tcltkSuffix)$(TclDebugExt).exe</tclShExeName>
<tkDLLName>$(tkPrefix)tk$(TkMajorVersion)$(TkMinorVersion)$(tcltkSuffix)$(TclDebugExt).dll</tkDLLName>
<tkLibName>$(tkPrefix)tk$(TclMajorVersion)$(TclMinorVersion)$(tcltkSuffix)$(TclDebugExt).lib</tkLibName>
<tclZlibDLLName>zlib1.dll</tclZlibDLLName> <tclZlibDLLName>zlib1.dll</tclZlibDLLName>
<tcltkLib>$(tcltkDir)lib\tcl$(TclMajorVersion)$(TclMinorVersion)t$(TclDebugExt).lib;$(tcltkDir)lib\tk$(TkMajorVersion)$(TkMinorVersion)t$(TclDebugExt).lib</tcltkLib> <tommathDLLName Condition="'$(TclMajorVersion)' == '9'">libtommath.dll</tommathDLLName>
<tommathLibName Condition="'$(TclMajorVersion)' == '9'">tommath.lib</tommathLibName>
<tcltkLib>$(tcltkDir)lib\$(TclLibName);$(tcltkDir)lib\$(TkLibName);</tcltkLib>
<tcltkLib Condition="'$(tommathLibName)' != ''">$(tcltkLib);$(tcltkDir)lib\$(tommathLibName)</tcltkLib>
<TclMachine>IX86</TclMachine> <TclMachine>IX86</TclMachine>
<TclMachine Condition="'$(Platform)' == 'x64'">AMD64</TclMachine> <TclMachine Condition="'$(Platform)' == 'x64'">AMD64</TclMachine>
<TclMachine Condition="'$(Platform)' == 'ARM64'">ARM64</TclMachine> <TclMachine Condition="'$(Platform)' == 'ARM64'">ARM64</TclMachine>