1import unittest 2import tkinter 3from tkinter import TclError 4import os 5from test.support import requires 6 7from test.test_tkinter.support import (requires_tk, tk_version, 8 get_tk_patchlevel, widget_eq, 9 AbstractDefaultRootTest) 10from test.test_tkinter.widget_tests import ( 11 add_standard_options, 12 AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests) 13 14requires('gui') 15 16 17EXPECTED_SCREEN_DISTANCE_ERRMSG = '(bad|expected) screen distance (but got )?"{}"' 18EXPECTED_SCREEN_DISTANCE_OR_EMPTY_ERRMSG = '(bad|expected) screen distance (or "" but got )?"{}"' 19 20def float_round(x): 21 return float(round(x)) 22 23 24class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests): 25 _conv_pad_pixels = False 26 27 def test_configure_class(self): 28 widget = self.create() 29 self.assertEqual(widget['class'], 30 widget.__class__.__name__.title()) 31 self.checkInvalidParam(widget, 'class', 'Foo', 32 errmsg="can't modify -class option after widget is created") 33 widget2 = self.create(class_='Foo') 34 self.assertEqual(widget2['class'], 'Foo') 35 36 def test_configure_colormap(self): 37 widget = self.create() 38 self.assertEqual(widget['colormap'], '') 39 self.checkInvalidParam(widget, 'colormap', 'new', 40 errmsg="can't modify -colormap option after widget is created") 41 widget2 = self.create(colormap='new') 42 self.assertEqual(widget2['colormap'], 'new') 43 44 def test_configure_container(self): 45 widget = self.create() 46 self.assertEqual(widget['container'], 0 if self.wantobjects else '0') 47 self.checkInvalidParam(widget, 'container', 1, 48 errmsg="can't modify -container option after widget is created") 49 widget2 = self.create(container=True) 50 self.assertEqual(widget2['container'], 1 if self.wantobjects else '1') 51 52 def test_configure_visual(self): 53 widget = self.create() 54 self.assertEqual(widget['visual'], '') 55 self.checkInvalidParam(widget, 'visual', 'default', 56 errmsg="can't modify -visual option after widget is created") 57 widget2 = self.create(visual='default') 58 self.assertEqual(widget2['visual'], 'default') 59 60 61@add_standard_options(StandardOptionsTests) 62class ToplevelTest(AbstractToplevelTest, unittest.TestCase): 63 OPTIONS = ( 64 'background', 'backgroundimage', 'borderwidth', 65 'class', 'colormap', 'container', 'cursor', 'height', 66 'highlightbackground', 'highlightcolor', 'highlightthickness', 67 'menu', 'padx', 'pady', 'relief', 'screen', 68 'takefocus', 'tile', 'use', 'visual', 'width', 69 ) 70 71 def create(self, **kwargs): 72 return tkinter.Toplevel(self.root, **kwargs) 73 74 def test_configure_menu(self): 75 widget = self.create() 76 menu = tkinter.Menu(self.root) 77 self.checkParam(widget, 'menu', menu, eq=widget_eq) 78 self.checkParam(widget, 'menu', '') 79 80 def test_configure_screen(self): 81 widget = self.create() 82 if widget._windowingsystem != 'x11': 83 self.skipTest('Not using Tk for X11') 84 self.assertEqual(widget['screen'], '') 85 try: 86 display = os.environ['DISPLAY'] 87 except KeyError: 88 self.skipTest('No $DISPLAY set.') 89 self.checkInvalidParam(widget, 'screen', display, 90 errmsg="can't modify -screen option after widget is created") 91 widget2 = self.create(screen=display) 92 self.assertEqual(widget2['screen'], display) 93 94 def test_configure_use(self): 95 widget = self.create() 96 self.assertEqual(widget['use'], '') 97 parent = self.create(container=True) 98 wid = hex(parent.winfo_id()) 99 with self.subTest(wid=wid): 100 widget2 = self.create(use=wid) 101 self.assertEqual(widget2['use'], wid) 102 103 104@add_standard_options(StandardOptionsTests) 105class FrameTest(AbstractToplevelTest, unittest.TestCase): 106 OPTIONS = ( 107 'background', 'backgroundimage', 'borderwidth', 108 'class', 'colormap', 'container', 'cursor', 'height', 109 'highlightbackground', 'highlightcolor', 'highlightthickness', 110 'padx', 'pady', 'relief', 'takefocus', 'tile', 'visual', 'width', 111 ) 112 113 def create(self, **kwargs): 114 return tkinter.Frame(self.root, **kwargs) 115 116 117@add_standard_options(StandardOptionsTests) 118class LabelFrameTest(AbstractToplevelTest, unittest.TestCase): 119 OPTIONS = ( 120 'background', 'borderwidth', 121 'class', 'colormap', 'container', 'cursor', 122 'font', 'foreground', 'height', 123 'highlightbackground', 'highlightcolor', 'highlightthickness', 124 'labelanchor', 'labelwidget', 'padx', 'pady', 'relief', 125 'takefocus', 'text', 'visual', 'width', 126 ) 127 128 def create(self, **kwargs): 129 return tkinter.LabelFrame(self.root, **kwargs) 130 131 def test_configure_labelanchor(self): 132 widget = self.create() 133 self.checkEnumParam(widget, 'labelanchor', 134 'e', 'en', 'es', 'n', 'ne', 'nw', 135 's', 'se', 'sw', 'w', 'wn', 'ws') 136 self.checkInvalidParam(widget, 'labelanchor', 'center') 137 138 def test_configure_labelwidget(self): 139 widget = self.create() 140 label = tkinter.Label(self.root, text='Mupp', name='foo') 141 self.checkParam(widget, 'labelwidget', label, expected='.foo') 142 label.destroy() 143 144 145class AbstractLabelTest(AbstractWidgetTest, IntegerSizeTests): 146 _conv_pixels = False 147 _clip_highlightthickness = tk_version >= (8, 7) 148 _clip_pad = tk_version >= (8, 7) 149 _clip_borderwidth = tk_version >= (8, 7) 150 151 152@add_standard_options(StandardOptionsTests) 153class LabelTest(AbstractLabelTest, unittest.TestCase): 154 OPTIONS = ( 155 'activebackground', 'activeforeground', 'anchor', 156 'background', 'bitmap', 'borderwidth', 'compound', 'cursor', 157 'disabledforeground', 'font', 'foreground', 'height', 158 'highlightbackground', 'highlightcolor', 'highlightthickness', 159 'image', 'justify', 'padx', 'pady', 'relief', 'state', 160 'takefocus', 'text', 'textvariable', 161 'underline', 'width', 'wraplength', 162 ) 163 164 def create(self, **kwargs): 165 return tkinter.Label(self.root, **kwargs) 166 167 168@add_standard_options(StandardOptionsTests) 169class ButtonTest(AbstractLabelTest, unittest.TestCase): 170 OPTIONS = ( 171 'activebackground', 'activeforeground', 'anchor', 172 'background', 'bitmap', 'borderwidth', 173 'command', 'compound', 'cursor', 'default', 174 'disabledforeground', 'font', 'foreground', 'height', 175 'highlightbackground', 'highlightcolor', 'highlightthickness', 176 'image', 'justify', 'overrelief', 'padx', 'pady', 'relief', 177 'repeatdelay', 'repeatinterval', 178 'state', 'takefocus', 'text', 'textvariable', 179 'underline', 'width', 'wraplength') 180 181 def create(self, **kwargs): 182 return tkinter.Button(self.root, **kwargs) 183 184 def test_configure_default(self): 185 widget = self.create() 186 self.checkEnumParam(widget, 'default', 'active', 'disabled', 'normal') 187 188 189@add_standard_options(StandardOptionsTests) 190class CheckbuttonTest(AbstractLabelTest, unittest.TestCase): 191 OPTIONS = ( 192 'activebackground', 'activeforeground', 'anchor', 193 'background', 'bitmap', 'borderwidth', 194 'command', 'compound', 'cursor', 195 'disabledforeground', 'font', 'foreground', 'height', 196 'highlightbackground', 'highlightcolor', 'highlightthickness', 197 'image', 'indicatoron', 'justify', 198 'offrelief', 'offvalue', 'onvalue', 'overrelief', 199 'padx', 'pady', 'relief', 'selectcolor', 'selectimage', 'state', 200 'takefocus', 'text', 'textvariable', 201 'tristateimage', 'tristatevalue', 202 'underline', 'variable', 'width', 'wraplength', 203 ) 204 205 def create(self, **kwargs): 206 return tkinter.Checkbutton(self.root, **kwargs) 207 208 209 def test_configure_offvalue(self): 210 widget = self.create() 211 self.checkParams(widget, 'offvalue', 1, 2.3, '', 'any string') 212 213 def test_configure_onvalue(self): 214 widget = self.create() 215 self.checkParams(widget, 'onvalue', 1, 2.3, '', 'any string') 216 217 def test_unique_variables(self): 218 frames = [] 219 buttons = [] 220 for i in range(2): 221 f = tkinter.Frame(self.root) 222 f.pack() 223 frames.append(f) 224 for j in 'AB': 225 b = tkinter.Checkbutton(f, text=j) 226 b.pack() 227 buttons.append(b) 228 variables = [str(b['variable']) for b in buttons] 229 self.assertEqual(len(set(variables)), 4, variables) 230 231 def test_same_name(self): 232 f1 = tkinter.Frame(self.root) 233 f2 = tkinter.Frame(self.root) 234 b1 = tkinter.Checkbutton(f1, name='test', text='Test1') 235 b2 = tkinter.Checkbutton(f2, name='test', text='Test2') 236 237 v = tkinter.IntVar(self.root, name='test') 238 b1.select() 239 self.assertEqual(v.get(), 1) 240 b2.deselect() 241 self.assertEqual(v.get(), 0) 242 243 244@add_standard_options(StandardOptionsTests) 245class RadiobuttonTest(AbstractLabelTest, unittest.TestCase): 246 OPTIONS = ( 247 'activebackground', 'activeforeground', 'anchor', 248 'background', 'bitmap', 'borderwidth', 249 'command', 'compound', 'cursor', 250 'disabledforeground', 'font', 'foreground', 'height', 251 'highlightbackground', 'highlightcolor', 'highlightthickness', 252 'image', 'indicatoron', 'justify', 'offrelief', 'overrelief', 253 'padx', 'pady', 'relief', 'selectcolor', 'selectimage', 'state', 254 'takefocus', 'text', 'textvariable', 255 'tristateimage', 'tristatevalue', 256 'underline', 'value', 'variable', 'width', 'wraplength', 257 ) 258 259 def create(self, **kwargs): 260 return tkinter.Radiobutton(self.root, **kwargs) 261 262 def test_configure_value(self): 263 widget = self.create() 264 self.checkParams(widget, 'value', 1, 2.3, '', 'any string') 265 266 267@add_standard_options(StandardOptionsTests) 268class MenubuttonTest(AbstractLabelTest, unittest.TestCase): 269 OPTIONS = ( 270 'activebackground', 'activeforeground', 'anchor', 271 'background', 'bitmap', 'borderwidth', 272 'compound', 'cursor', 'direction', 273 'disabledforeground', 'font', 'foreground', 'height', 274 'highlightbackground', 'highlightcolor', 'highlightthickness', 275 'image', 'indicatoron', 'justify', 'menu', 276 'padx', 'pady', 'relief', 'state', 277 'takefocus', 'text', 'textvariable', 278 'underline', 'width', 'wraplength', 279 ) 280 _conv_pixels = round 281 _clip_highlightthickness = True 282 _clip_pad = True 283 _clip_borderwidth = False 284 285 def create(self, **kwargs): 286 return tkinter.Menubutton(self.root, **kwargs) 287 288 def test_configure_direction(self): 289 widget = self.create() 290 self.checkEnumParam(widget, 'direction', 291 'above', 'below', 'flush', 'left', 'right') 292 293 def test_configure_height(self): 294 widget = self.create() 295 self.checkIntegerParam(widget, 'height', 100, -100, 0, conv=str) 296 297 def test_configure_image(self): 298 widget = self.create() 299 image = tkinter.PhotoImage(master=self.root, name='image1') 300 self.checkParam(widget, 'image', image, conv=str) 301 errmsg = 'image "spam" doesn\'t exist' 302 with self.assertRaises(tkinter.TclError) as cm: 303 widget['image'] = 'spam' 304 if errmsg is not None: 305 self.assertEqual(str(cm.exception), errmsg) 306 with self.assertRaises(tkinter.TclError) as cm: 307 widget.configure({'image': 'spam'}) 308 if errmsg is not None: 309 self.assertEqual(str(cm.exception), errmsg) 310 311 def test_configure_menu(self): 312 widget = self.create() 313 menu = tkinter.Menu(widget, name='menu') 314 self.checkParam(widget, 'menu', menu, eq=widget_eq) 315 menu.destroy() 316 317 def test_configure_width(self): 318 widget = self.create() 319 self.checkIntegerParam(widget, 'width', 402, -402, 0, conv=str) 320 321 322class OptionMenuTest(MenubuttonTest, unittest.TestCase): 323 324 def create(self, default='b', values=('a', 'b', 'c'), **kwargs): 325 return tkinter.OptionMenu(self.root, None, default, *values, **kwargs) 326 327 def test_bad_kwarg(self): 328 with self.assertRaisesRegex(TclError, r"^unknown option -image$"): 329 tkinter.OptionMenu(self.root, None, 'b', image='') 330 331 332@add_standard_options(IntegerSizeTests, StandardOptionsTests) 333class EntryTest(AbstractWidgetTest, unittest.TestCase): 334 OPTIONS = ( 335 'background', 'borderwidth', 'cursor', 336 'disabledbackground', 'disabledforeground', 337 'exportselection', 'font', 'foreground', 338 'highlightbackground', 'highlightcolor', 'highlightthickness', 339 'insertbackground', 'insertborderwidth', 340 'insertofftime', 'insertontime', 'insertwidth', 341 'invalidcommand', 'justify', 'placeholder', 'placeholderforeground', 342 'readonlybackground', 'relief', 343 'selectbackground', 'selectborderwidth', 'selectforeground', 344 'show', 'state', 'takefocus', 'textvariable', 345 'validate', 'validatecommand', 'width', 'xscrollcommand', 346 ) 347 348 def create(self, **kwargs): 349 return tkinter.Entry(self.root, **kwargs) 350 351 def test_configure_disabledbackground(self): 352 widget = self.create() 353 self.checkColorParam(widget, 'disabledbackground') 354 355 def test_configure_insertborderwidth(self): 356 widget = self.create(insertwidth=100) 357 self.checkPixelsParam(widget, 'insertborderwidth', 358 0, 1.3, 2.6, 6, -2, '10p') 359 # insertborderwidth is bounded above by a half of insertwidth. 360 self.checkParam(widget, 'insertborderwidth', 60, expected=100//2) 361 362 def test_configure_insertwidth(self): 363 widget = self.create() 364 self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, '10p') 365 self.checkParam(widget, 'insertwidth', 0.1, expected=2) 366 self.checkParam(widget, 'insertwidth', -2, expected=2) 367 self.checkParam(widget, 'insertwidth', 0.9, expected=1) 368 369 def test_configure_invalidcommand(self): 370 widget = self.create() 371 self.checkCommandParam(widget, 'invalidcommand') 372 self.checkCommandParam(widget, 'invcmd') 373 374 def test_configure_readonlybackground(self): 375 widget = self.create() 376 self.checkColorParam(widget, 'readonlybackground') 377 378 def test_configure_show(self): 379 widget = self.create() 380 self.checkParam(widget, 'show', '*') 381 self.checkParam(widget, 'show', '') 382 self.checkParam(widget, 'show', ' ') 383 384 def test_configure_state(self): 385 widget = self.create() 386 self.checkEnumParam(widget, 'state', 387 'disabled', 'normal', 'readonly') 388 389 def test_configure_validate(self): 390 widget = self.create() 391 self.checkEnumParam(widget, 'validate', 392 'all', 'key', 'focus', 'focusin', 'focusout', 'none') 393 394 def test_configure_validatecommand(self): 395 widget = self.create() 396 self.checkCommandParam(widget, 'validatecommand') 397 self.checkCommandParam(widget, 'vcmd') 398 399 def test_selection_methods(self): 400 widget = self.create() 401 widget.insert(0, '12345') 402 self.assertFalse(widget.selection_present()) 403 widget.selection_range(0, 'end') 404 self.assertEqual(widget.selection_get(), '12345') 405 self.assertTrue(widget.selection_present()) 406 widget.selection_from(1) 407 widget.selection_to(2) 408 self.assertEqual(widget.selection_get(), '2') 409 widget.selection_range(3, 4) 410 self.assertEqual(widget.selection_get(), '4') 411 widget.selection_clear() 412 self.assertFalse(widget.selection_present()) 413 widget.selection_range(0, 'end') 414 widget.selection_adjust(4) 415 self.assertEqual(widget.selection_get(), '1234') 416 widget.selection_adjust(1) 417 self.assertEqual(widget.selection_get(), '234') 418 widget.selection_adjust(5) 419 self.assertEqual(widget.selection_get(), '2345') 420 widget.selection_adjust(0) 421 self.assertEqual(widget.selection_get(), '12345') 422 widget.selection_adjust(0) 423 424 425@add_standard_options(StandardOptionsTests) 426class SpinboxTest(EntryTest, unittest.TestCase): 427 OPTIONS = ( 428 'activebackground', 'background', 'borderwidth', 429 'buttonbackground', 'buttoncursor', 'buttondownrelief', 'buttonuprelief', 430 'command', 'cursor', 'disabledbackground', 'disabledforeground', 431 'exportselection', 'font', 'foreground', 'format', 'from', 432 'highlightbackground', 'highlightcolor', 'highlightthickness', 433 'increment', 434 'insertbackground', 'insertborderwidth', 435 'insertofftime', 'insertontime', 'insertwidth', 436 'invalidcommand', 'justify', 'placeholder', 'placeholderforeground', 437 'relief', 'readonlybackground', 'repeatdelay', 'repeatinterval', 438 'selectbackground', 'selectborderwidth', 'selectforeground', 439 'state', 'takefocus', 'textvariable', 'to', 440 'validate', 'validatecommand', 'values', 441 'width', 'wrap', 'xscrollcommand', 442 ) 443 444 def create(self, **kwargs): 445 return tkinter.Spinbox(self.root, **kwargs) 446 447 test_configure_show = None 448 449 def test_configure_buttonbackground(self): 450 widget = self.create() 451 self.checkColorParam(widget, 'buttonbackground') 452 453 def test_configure_buttoncursor(self): 454 widget = self.create() 455 self.checkCursorParam(widget, 'buttoncursor') 456 457 def test_configure_buttondownrelief(self): 458 widget = self.create() 459 self.checkReliefParam(widget, 'buttondownrelief') 460 461 def test_configure_buttonuprelief(self): 462 widget = self.create() 463 self.checkReliefParam(widget, 'buttonuprelief') 464 465 def test_configure_format(self): 466 widget = self.create() 467 self.checkParam(widget, 'format', '%2f') 468 self.checkParam(widget, 'format', '%2.2f') 469 self.checkParam(widget, 'format', '%.2f') 470 self.checkParam(widget, 'format', '%2.f') 471 self.checkInvalidParam(widget, 'format', '%2e-1f') 472 self.checkInvalidParam(widget, 'format', '2.2') 473 self.checkInvalidParam(widget, 'format', '%2.-2f') 474 self.checkParam(widget, 'format', '%-2.02f') 475 self.checkParam(widget, 'format', '% 2.02f') 476 self.checkParam(widget, 'format', '% -2.200f') 477 self.checkParam(widget, 'format', '%09.200f') 478 self.checkInvalidParam(widget, 'format', '%d') 479 480 def test_configure_from(self): 481 widget = self.create() 482 self.checkParam(widget, 'to', 100.0) 483 self.checkFloatParam(widget, 'from', -10, 10.2, 11.7) 484 if tk_version >= (8, 7): 485 self.checkFloatParam(widget, 'from', 200, expected=100) 486 else: 487 self.checkInvalidParam( 488 widget, 'from', 200, 489 errmsg='-to value must be greater than -from value') 490 491 def test_configure_increment(self): 492 widget = self.create() 493 self.checkFloatParam(widget, 'increment', -1, 1, 10.2, 12.8, 0) 494 495 def test_configure_to(self): 496 widget = self.create() 497 self.checkParam(widget, 'from', -100.0) 498 self.checkFloatParam(widget, 'to', -10, 10.2, 11.7) 499 if tk_version >= (8, 7): 500 self.checkFloatParam(widget, 'to', -200, expected=-100) 501 else: 502 self.checkInvalidParam( 503 widget, 'to', -200, 504 errmsg='-to value must be greater than -from value') 505 506 def test_configure_values(self): 507 # XXX 508 widget = self.create() 509 self.assertEqual(widget['values'], '') 510 self.checkParam(widget, 'values', 'mon tue wed thur') 511 self.checkParam(widget, 'values', ('mon', 'tue', 'wed', 'thur'), 512 expected='mon tue wed thur') 513 self.checkParam(widget, 'values', (42, 3.14, '', 'any string'), 514 expected='42 3.14 {} {any string}') 515 self.checkParam(widget, 'values', '') 516 517 def test_configure_wrap(self): 518 widget = self.create() 519 self.checkBooleanParam(widget, 'wrap') 520 521 def test_bbox(self): 522 widget = self.create() 523 self.assertIsBoundingBox(widget.bbox(0)) 524 self.assertRaises(tkinter.TclError, widget.bbox, 'noindex') 525 self.assertRaises(tkinter.TclError, widget.bbox, None) 526 self.assertRaises(TypeError, widget.bbox) 527 self.assertRaises(TypeError, widget.bbox, 0, 1) 528 529 def test_selection_methods(self): 530 widget = self.create() 531 widget.insert(0, '12345') 532 self.assertFalse(widget.selection_present()) 533 widget.selection_range(0, 'end') 534 self.assertEqual(widget.selection_get(), '12345') 535 self.assertTrue(widget.selection_present()) 536 widget.selection_from(1) 537 widget.selection_to(2) 538 self.assertEqual(widget.selection_get(), '2') 539 widget.selection_range(3, 4) 540 self.assertEqual(widget.selection_get(), '4') 541 widget.selection_clear() 542 self.assertFalse(widget.selection_present()) 543 widget.selection_range(0, 'end') 544 widget.selection_adjust(4) 545 self.assertEqual(widget.selection_get(), '1234') 546 widget.selection_adjust(1) 547 self.assertEqual(widget.selection_get(), '234') 548 widget.selection_adjust(5) 549 self.assertEqual(widget.selection_get(), '2345') 550 widget.selection_adjust(0) 551 self.assertEqual(widget.selection_get(), '12345') 552 553 def test_selection_element(self): 554 widget = self.create() 555 self.assertEqual(widget.selection_element(), "none") 556 widget.selection_element("buttonup") 557 self.assertEqual(widget.selection_element(), "buttonup") 558 widget.selection_element("buttondown") 559 self.assertEqual(widget.selection_element(), "buttondown") 560 561 562@add_standard_options(StandardOptionsTests) 563class TextTest(AbstractWidgetTest, unittest.TestCase): 564 OPTIONS = ( 565 'autoseparators', 'background', 'blockcursor', 'borderwidth', 566 'cursor', 'endline', 'exportselection', 567 'font', 'foreground', 'height', 568 'highlightbackground', 'highlightcolor', 'highlightthickness', 569 'inactiveselectbackground', 'insertbackground', 'insertborderwidth', 570 'insertofftime', 'insertontime', 'insertunfocussed', 'insertwidth', 571 'maxundo', 'padx', 'pady', 'relief', 572 'selectbackground', 'selectborderwidth', 'selectforeground', 573 'setgrid', 'spacing1', 'spacing2', 'spacing3', 'startline', 'state', 574 'tabs', 'tabstyle', 'takefocus', 'undo', 'width', 'wrap', 575 'xscrollcommand', 'yscrollcommand', 576 ) 577 578 def create(self, **kwargs): 579 return tkinter.Text(self.root, **kwargs) 580 581 def test_configure_autoseparators(self): 582 widget = self.create() 583 self.checkBooleanParam(widget, 'autoseparators') 584 585 def test_configure_blockcursor(self): 586 widget = self.create() 587 self.checkBooleanParam(widget, 'blockcursor') 588 589 def test_configure_endline(self): 590 widget = self.create() 591 text = '\n'.join('Line %d' for i in range(100)) 592 widget.insert('end', text) 593 self.checkParam(widget, 'endline', 200, expected='') 594 self.checkParam(widget, 'endline', -10, expected='') 595 self.checkInvalidParam(widget, 'endline', 'spam', 596 errmsg='expected integer but got "spam"') 597 self.checkParam(widget, 'endline', 50) 598 self.checkParam(widget, 'startline', 15) 599 self.checkInvalidParam(widget, 'endline', 10, 600 errmsg='-startline must be less than or equal to -endline') 601 602 def test_configure_height(self): 603 widget = self.create() 604 self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, '3c') 605 self.checkParam(widget, 'height', -100, expected=1) 606 self.checkParam(widget, 'height', 0, expected=1) 607 608 def test_configure_maxundo(self): 609 widget = self.create() 610 self.checkIntegerParam(widget, 'maxundo', 0, 5, -1) 611 612 def test_configure_inactiveselectbackground(self): 613 widget = self.create() 614 self.checkColorParam(widget, 'inactiveselectbackground') 615 616 @requires_tk(8, 6) 617 def test_configure_insertunfocussed(self): 618 widget = self.create() 619 self.checkEnumParam(widget, 'insertunfocussed', 620 'hollow', 'none', 'solid') 621 622 def test_configure_selectborderwidth(self): 623 widget = self.create() 624 self.checkPixelsParam(widget, 'selectborderwidth', 625 1.3, 2.6, -2, '10p', conv=False) 626 627 def test_configure_spacing1(self): 628 widget = self.create() 629 self.checkPixelsParam(widget, 'spacing1', 20, 21.4, 22.6, '0.5c') 630 self.checkParam(widget, 'spacing1', -5, expected=0) 631 632 def test_configure_spacing2(self): 633 widget = self.create() 634 self.checkPixelsParam(widget, 'spacing2', 5, 6.4, 7.6, '0.1c') 635 self.checkParam(widget, 'spacing2', -1, expected=0) 636 637 def test_configure_spacing3(self): 638 widget = self.create() 639 self.checkPixelsParam(widget, 'spacing3', 20, 21.4, 22.6, '0.5c') 640 self.checkParam(widget, 'spacing3', -10, expected=0) 641 642 def test_configure_startline(self): 643 widget = self.create() 644 text = '\n'.join('Line %d' for i in range(100)) 645 widget.insert('end', text) 646 self.checkParam(widget, 'startline', 200, expected='') 647 self.checkParam(widget, 'startline', -10, expected='') 648 self.checkInvalidParam(widget, 'startline', 'spam', 649 errmsg='expected integer but got "spam"') 650 self.checkParam(widget, 'startline', 10) 651 self.checkParam(widget, 'endline', 50) 652 self.checkInvalidParam(widget, 'startline', 70, 653 errmsg='-startline must be less than or equal to -endline') 654 655 def test_configure_state(self): 656 widget = self.create() 657 self.checkEnumParam(widget, 'state', 'disabled', 'normal') 658 659 def test_configure_tabs(self): 660 widget = self.create() 661 self.checkParam(widget, 'tabs', (10.2, 20.7, '1i', '2i')) 662 self.checkParam(widget, 'tabs', '10.2 20.7 1i 2i', 663 expected=(10.2, 20.7, '1i', '2i') 664 if get_tk_patchlevel(self.root) >= (8, 6, 14) 665 else ('10.2', '20.7', '1i', '2i')) 666 self.checkParam(widget, 'tabs', '2c left 4c 6c center', 667 expected=('2c', 'left', '4c', '6c', 'center')) 668 self.checkInvalidParam(widget, 'tabs', 'spam', 669 errmsg=EXPECTED_SCREEN_DISTANCE_ERRMSG.format('spam')) 670 671 def test_configure_tabstyle(self): 672 widget = self.create() 673 self.checkEnumParam(widget, 'tabstyle', 'tabular', 'wordprocessor') 674 675 def test_configure_undo(self): 676 widget = self.create() 677 self.checkBooleanParam(widget, 'undo') 678 679 def test_configure_width(self): 680 widget = self.create() 681 self.checkIntegerParam(widget, 'width', 402) 682 self.checkParam(widget, 'width', -402, expected=1) 683 self.checkParam(widget, 'width', 0, expected=1) 684 685 def test_configure_wrap(self): 686 widget = self.create() 687 self.checkEnumParam(widget, 'wrap', 'char', 'none', 'word') 688 689 def test_bbox(self): 690 widget = self.create() 691 self.assertIsBoundingBox(widget.bbox('1.1')) 692 self.assertIsNone(widget.bbox('end')) 693 self.assertRaises(tkinter.TclError, widget.bbox, 'noindex') 694 self.assertRaises(tkinter.TclError, widget.bbox, None) 695 self.assertRaises(TypeError, widget.bbox) 696 self.assertRaises(TypeError, widget.bbox, '1.1', 'end') 697 698 699@add_standard_options(PixelSizeTests, StandardOptionsTests) 700class CanvasTest(AbstractWidgetTest, unittest.TestCase): 701 OPTIONS = ( 702 'background', 'borderwidth', 703 'closeenough', 'confine', 'cursor', 'height', 704 'highlightbackground', 'highlightcolor', 'highlightthickness', 705 'insertbackground', 'insertborderwidth', 706 'insertofftime', 'insertontime', 'insertwidth', 707 'offset', 'relief', 'scrollregion', 708 'selectbackground', 'selectborderwidth', 'selectforeground', 709 'state', 'takefocus', 710 'xscrollcommand', 'xscrollincrement', 711 'yscrollcommand', 'yscrollincrement', 'width', 712 ) 713 714 _conv_pixels = round 715 _stringify = True 716 717 def create(self, **kwargs): 718 return tkinter.Canvas(self.root, **kwargs) 719 720 def test_configure_closeenough(self): 721 widget = self.create() 722 self.checkFloatParam(widget, 'closeenough', 24, 2.4, 3.6, -3, 723 conv=float) 724 725 def test_configure_confine(self): 726 widget = self.create() 727 self.checkBooleanParam(widget, 'confine') 728 729 def test_configure_offset(self): 730 widget = self.create() 731 self.assertEqual(widget['offset'], '0,0') 732 self.checkParams(widget, 'offset', 733 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'center') 734 self.checkParam(widget, 'offset', '10,20') 735 self.checkParam(widget, 'offset', '#5,6') 736 self.checkInvalidParam(widget, 'offset', 'spam') 737 738 def test_configure_scrollregion(self): 739 widget = self.create() 740 self.checkParam(widget, 'scrollregion', '0 0 200 150') 741 self.checkParam(widget, 'scrollregion', (0, 0, 200, 150), 742 expected='0 0 200 150') 743 self.checkParam(widget, 'scrollregion', '') 744 self.checkInvalidParam(widget, 'scrollregion', 'spam', 745 errmsg='bad scrollRegion "spam"') 746 self.checkInvalidParam(widget, 'scrollregion', (0, 0, 200, 'spam')) 747 self.checkInvalidParam(widget, 'scrollregion', (0, 0, 200)) 748 self.checkInvalidParam(widget, 'scrollregion', (0, 0, 200, 150, 0)) 749 750 def test_configure_state(self): 751 widget = self.create() 752 self.checkEnumParam(widget, 'state', 'disabled', 'normal', 753 errmsg='bad state value "{}": must be normal or disabled') 754 755 def test_configure_xscrollincrement(self): 756 widget = self.create() 757 self.checkPixelsParam(widget, 'xscrollincrement', 758 40, 0, 41.2, 43.6, -40, '0.5i') 759 760 def test_configure_yscrollincrement(self): 761 widget = self.create() 762 self.checkPixelsParam(widget, 'yscrollincrement', 763 10, 0, 11.2, 13.6, -10, '0.1i') 764 765 def _test_option_joinstyle(self, c, factory): 766 for joinstyle in 'bevel', 'miter', 'round': 767 i = factory(joinstyle=joinstyle) 768 self.assertEqual(c.itemcget(i, 'joinstyle'), joinstyle) 769 self.assertRaises(TclError, factory, joinstyle='spam') 770 771 def _test_option_smooth(self, c, factory): 772 for smooth in 1, True, '1', 'true', 'yes', 'on': 773 i = factory(smooth=smooth) 774 self.assertEqual(c.itemcget(i, 'smooth'), 'true') 775 for smooth in 0, False, '0', 'false', 'no', 'off': 776 i = factory(smooth=smooth) 777 self.assertEqual(c.itemcget(i, 'smooth'), '0') 778 i = factory(smooth=True, splinestep=30) 779 self.assertEqual(c.itemcget(i, 'smooth'), 'true') 780 self.assertEqual(c.itemcget(i, 'splinestep'), '30') 781 i = factory(smooth='raw', splinestep=30) 782 self.assertEqual(c.itemcget(i, 'smooth'), 'raw') 783 self.assertEqual(c.itemcget(i, 'splinestep'), '30') 784 self.assertRaises(TclError, factory, smooth='spam') 785 786 def test_create_rectangle(self): 787 c = self.create() 788 i1 = c.create_rectangle(20, 30, 60, 10) 789 self.assertEqual(c.coords(i1), [20.0, 10.0, 60.0, 30.0]) 790 self.assertEqual(c.bbox(i1), (19, 9, 61, 31)) 791 792 i2 = c.create_rectangle([21, 31, 61, 11]) 793 self.assertEqual(c.coords(i2), [21.0, 11.0, 61.0, 31.0]) 794 self.assertEqual(c.bbox(i2), (20, 10, 62, 32)) 795 796 i3 = c.create_rectangle((22, 32), (62, 12)) 797 self.assertEqual(c.coords(i3), [22.0, 12.0, 62.0, 32.0]) 798 self.assertEqual(c.bbox(i3), (21, 11, 63, 33)) 799 800 i4 = c.create_rectangle([(23, 33), (63, 13)]) 801 self.assertEqual(c.coords(i4), [23.0, 13.0, 63.0, 33.0]) 802 self.assertEqual(c.bbox(i4), (22, 12, 64, 34)) 803 804 self.assertRaises(TclError, c.create_rectangle, 20, 30, 60) 805 self.assertRaises(TclError, c.create_rectangle, [20, 30, 60]) 806 self.assertRaises(TclError, c.create_rectangle, 20, 30, 40, 50, 60, 10) 807 self.assertRaises(TclError, c.create_rectangle, [20, 30, 40, 50, 60, 10]) 808 self.assertRaises(TclError, c.create_rectangle, 20, 30) 809 self.assertRaises(TclError, c.create_rectangle, [20, 30]) 810 self.assertRaises(IndexError, c.create_rectangle) 811 self.assertRaises(IndexError, c.create_rectangle, []) 812 813 def test_create_line(self): 814 c = self.create() 815 i1 = c.create_line(20, 30, 40, 50, 60, 10) 816 self.assertEqual(c.coords(i1), [20.0, 30.0, 40.0, 50.0, 60.0, 10.0]) 817 self.assertEqual(c.bbox(i1), (18, 8, 62, 52)) 818 self.assertEqual(c.itemcget(i1, 'arrow'), 'none') 819 self.assertEqual(c.itemcget(i1, 'arrowshape'), '8 10 3') 820 self.assertEqual(c.itemcget(i1, 'capstyle'), 'butt') 821 self.assertEqual(c.itemcget(i1, 'joinstyle'), 'round') 822 self.assertEqual(c.itemcget(i1, 'smooth'), '0') 823 self.assertEqual(c.itemcget(i1, 'splinestep'), '12') 824 825 i2 = c.create_line([21, 31, 41, 51, 61, 11]) 826 self.assertEqual(c.coords(i2), [21.0, 31.0, 41.0, 51.0, 61.0, 11.0]) 827 self.assertEqual(c.bbox(i2), (19, 9, 63, 53)) 828 829 i3 = c.create_line((22, 32), (42, 52), (62, 12)) 830 self.assertEqual(c.coords(i3), [22.0, 32.0, 42.0, 52.0, 62.0, 12.0]) 831 self.assertEqual(c.bbox(i3), (20, 10, 64, 54)) 832 833 i4 = c.create_line([(23, 33), (43, 53), (63, 13)]) 834 self.assertEqual(c.coords(i4), [23.0, 33.0, 43.0, 53.0, 63.0, 13.0]) 835 self.assertEqual(c.bbox(i4), (21, 11, 65, 55)) 836 837 self.assertRaises(TclError, c.create_line, 20, 30, 60) 838 self.assertRaises(TclError, c.create_line, [20, 30, 60]) 839 self.assertRaises(TclError, c.create_line, 20, 30) 840 self.assertRaises(TclError, c.create_line, [20, 30]) 841 self.assertRaises(IndexError, c.create_line) 842 self.assertRaises(IndexError, c.create_line, []) 843 844 for arrow in 'none', 'first', 'last', 'both': 845 i = c.create_line(20, 30, 60, 10, arrow=arrow) 846 self.assertEqual(c.itemcget(i, 'arrow'), arrow) 847 i = c.create_line(20, 30, 60, 10, arrow='first', arrowshape=[10, 15, 5]) 848 self.assertEqual(c.itemcget(i, 'arrowshape'), '10 15 5') 849 self.assertRaises(TclError, c.create_line, 20, 30, 60, 10, arrow='spam') 850 851 for capstyle in 'butt', 'projecting', 'round': 852 i = c.create_line(20, 30, 60, 10, capstyle=capstyle) 853 self.assertEqual(c.itemcget(i, 'capstyle'), capstyle) 854 self.assertRaises(TclError, c.create_line, 20, 30, 60, 10, capstyle='spam') 855 856 self._test_option_joinstyle(c, 857 lambda **kwargs: c.create_line(20, 30, 40, 50, 60, 10, **kwargs)) 858 self._test_option_smooth(c, 859 lambda **kwargs: c.create_line(20, 30, 60, 10, **kwargs)) 860 861 def test_create_polygon(self): 862 c = self.create() 863 tk87 = tk_version >= (8, 7) 864 # In Tk < 8.7 polygons are filled, but has no outline by default. 865 # This affects its size, so always explicitly specify outline. 866 i1 = c.create_polygon(20, 30, 40, 50, 60, 10, outline='red') 867 self.assertEqual(c.coords(i1), [20.0, 30.0, 40.0, 50.0, 60.0, 10.0]) 868 self.assertEqual(c.bbox(i1), (18, 8, 62, 52)) 869 self.assertEqual(c.itemcget(i1, 'joinstyle'), 'round') 870 self.assertEqual(c.itemcget(i1, 'smooth'), '0') 871 self.assertEqual(c.itemcget(i1, 'splinestep'), '12') 872 873 i2 = c.create_polygon([21, 31, 41, 51, 61, 11], outline='red') 874 self.assertEqual(c.coords(i2), [21.0, 31.0, 41.0, 51.0, 61.0, 11.0]) 875 self.assertEqual(c.bbox(i2), (19, 9, 63, 53)) 876 877 i3 = c.create_polygon((22, 32), (42, 52), (62, 12), outline='red') 878 self.assertEqual(c.coords(i3), [22.0, 32.0, 42.0, 52.0, 62.0, 12.0]) 879 self.assertEqual(c.bbox(i3), (20, 10, 64, 54)) 880 881 i4 = c.create_polygon([(23, 33), (43, 53), (63, 13)], outline='red') 882 self.assertEqual(c.coords(i4), [23.0, 33.0, 43.0, 53.0, 63.0, 13.0]) 883 self.assertEqual(c.bbox(i4), (21, 11, 65, 55)) 884 885 self.assertRaises(TclError, c.create_polygon, 20, 30, 60) 886 self.assertRaises(TclError, c.create_polygon, [20, 30, 60]) 887 self.assertRaises(IndexError, c.create_polygon) 888 self.assertRaises(IndexError, c.create_polygon, []) 889 890 self._test_option_joinstyle(c, 891 lambda **kwargs: c.create_polygon(20, 30, 40, 50, 60, 10, **kwargs)) 892 self._test_option_smooth(c, 893 lambda **kwargs: c.create_polygon(20, 30, 40, 50, 60, 10, **kwargs)) 894 895 def test_coords(self): 896 c = self.create() 897 i = c.create_line(20, 30, 40, 50, 60, 10, tags='x') 898 self.assertEqual(c.coords(i), [20.0, 30.0, 40.0, 50.0, 60.0, 10.0]) 899 self.assertEqual(c.coords('x'), [20.0, 30.0, 40.0, 50.0, 60.0, 10.0]) 900 self.assertEqual(c.bbox(i), (18, 8, 62, 52)) 901 902 c.coords(i, 50, 60, 70, 80, 90, 40) 903 self.assertEqual(c.coords(i), [50.0, 60.0, 70.0, 80.0, 90.0, 40.0]) 904 self.assertEqual(c.bbox(i), (48, 38, 92, 82)) 905 906 c.coords(i, [21, 31, 41, 51, 61, 11]) 907 self.assertEqual(c.coords(i), [21.0, 31.0, 41.0, 51.0, 61.0, 11.0]) 908 909 c.coords(i, (22, 32), (42, 52), (62, 12)) 910 self.assertEqual(c.coords(i), [22.0, 32.0, 42.0, 52.0, 62.0, 12.0]) 911 912 c.coords(i, [(23, 33), (43, 53), (63, 13)]) 913 self.assertEqual(c.coords(i), [23.0, 33.0, 43.0, 53.0, 63.0, 13.0]) 914 915 c.coords(i, 20, 30, 60, 10) 916 self.assertEqual(c.coords(i), [20.0, 30.0, 60.0, 10.0]) 917 self.assertEqual(c.bbox(i), (18, 8, 62, 32)) 918 919 self.assertRaises(TclError, c.coords, i, 20, 30, 60) 920 self.assertRaises(TclError, c.coords, i, [20, 30, 60]) 921 self.assertRaises(TclError, c.coords, i, 20, 30) 922 self.assertRaises(TclError, c.coords, i, [20, 30]) 923 924 c.coords(i, '20', '30c', '60i', '10p') 925 coords = c.coords(i) 926 self.assertIsInstance(coords, list) 927 self.assertEqual(len(coords), 4) 928 self.assertEqual(coords[0], 20) 929 for i in range(4): 930 self.assertIsInstance(coords[i], float) 931 932 @requires_tk(8, 6) 933 def test_moveto(self): 934 widget = self.create() 935 i1 = widget.create_rectangle(1, 1, 20, 20, tags='group') 936 i2 = widget.create_rectangle(30, 30, 50, 70, tags='group') 937 x1, y1, _, _ = widget.bbox(i1) 938 x2, y2, _, _ = widget.bbox(i2) 939 widget.moveto('group', 200, 100) 940 x1_2, y1_2, _, _ = widget.bbox(i1) 941 x2_2, y2_2, _, _ = widget.bbox(i2) 942 self.assertEqual(x1_2, 200) 943 self.assertEqual(y1_2, 100) 944 self.assertEqual(x2 - x1, x2_2 - x1_2) 945 self.assertEqual(y2 - y1, y2_2 - y1_2) 946 widget.tag_lower(i2, i1) 947 widget.moveto('group', y=50) 948 x1_3, y1_3, _, _ = widget.bbox(i1) 949 x2_3, y2_3, _, _ = widget.bbox(i2) 950 self.assertEqual(y2_3, 50) 951 self.assertEqual(x2_3, x2_2) 952 self.assertEqual(x2_2 - x1_2, x2_3 - x1_3) 953 self.assertEqual(y2_2 - y1_2, y2_3 - y1_3) 954 955 956@add_standard_options(IntegerSizeTests, StandardOptionsTests) 957class ListboxTest(AbstractWidgetTest, unittest.TestCase): 958 OPTIONS = ( 959 'activestyle', 'background', 'borderwidth', 'cursor', 960 'disabledforeground', 'exportselection', 961 'font', 'foreground', 'height', 962 'highlightbackground', 'highlightcolor', 'highlightthickness', 963 'justify', 'listvariable', 'relief', 964 'selectbackground', 'selectborderwidth', 'selectforeground', 965 'selectmode', 'setgrid', 'state', 966 'takefocus', 'width', 'xscrollcommand', 'yscrollcommand', 967 ) 968 969 def create(self, **kwargs): 970 return tkinter.Listbox(self.root, **kwargs) 971 972 def test_configure_activestyle(self): 973 widget = self.create() 974 self.checkEnumParam(widget, 'activestyle', 975 'dotbox', 'none', 'underline') 976 977 test_configure_justify = requires_tk(8, 6, 5)(StandardOptionsTests.test_configure_justify) 978 979 def test_configure_listvariable(self): 980 widget = self.create() 981 var = tkinter.DoubleVar(self.root) 982 self.checkVariableParam(widget, 'listvariable', var) 983 984 def test_configure_selectmode(self): 985 widget = self.create() 986 self.checkParam(widget, 'selectmode', 'single') 987 self.checkParam(widget, 'selectmode', 'browse') 988 self.checkParam(widget, 'selectmode', 'multiple') 989 self.checkParam(widget, 'selectmode', 'extended') 990 991 def test_configure_state(self): 992 widget = self.create() 993 self.checkEnumParam(widget, 'state', 'disabled', 'normal') 994 995 def test_itemconfigure(self): 996 widget = self.create() 997 with self.assertRaisesRegex(TclError, 'item number "0" out of range'): 998 widget.itemconfigure(0) 999 colors = 'red orange yellow green blue white violet'.split() 1000 widget.insert('end', *colors) 1001 for i, color in enumerate(colors): 1002 widget.itemconfigure(i, background=color) 1003 with self.assertRaises(TypeError): 1004 widget.itemconfigure() 1005 with self.assertRaisesRegex(TclError, 'bad listbox index "red"'): 1006 widget.itemconfigure('red') 1007 if get_tk_patchlevel(self.root) >= (8, 6, 14): 1008 prefix = ('background', '', '', '') 1009 else: 1010 prefix = ('background', 'background', 'Background', '') 1011 self.assertEqual(widget.itemconfigure(0, 'background'), 1012 (*prefix, 'red')) 1013 self.assertEqual(widget.itemconfigure('end', 'background'), 1014 (*prefix, 'violet')) 1015 self.assertEqual(widget.itemconfigure('@0,0', 'background'), 1016 (*prefix, 'red')) 1017 1018 d = widget.itemconfigure(0) 1019 self.assertIsInstance(d, dict) 1020 for k, v in d.items(): 1021 self.assertIn(len(v), (2, 5)) 1022 if len(v) == 5: 1023 self.assertEqual(v, widget.itemconfigure(0, k)) 1024 self.assertEqual(v[4], widget.itemcget(0, k)) 1025 1026 def check_itemconfigure(self, name, value): 1027 widget = self.create() 1028 widget.insert('end', 'a', 'b', 'c', 'd') 1029 widget.itemconfigure(0, **{name: value}) 1030 self.assertEqual(widget.itemconfigure(0, name)[4], value) 1031 self.assertEqual(widget.itemcget(0, name), value) 1032 with self.assertRaisesRegex(TclError, 'unknown color name "spam"'): 1033 widget.itemconfigure(0, **{name: 'spam'}) 1034 1035 def test_itemconfigure_background(self): 1036 self.check_itemconfigure('background', '#ff0000') 1037 1038 def test_itemconfigure_bg(self): 1039 self.check_itemconfigure('bg', '#ff0000') 1040 1041 def test_itemconfigure_fg(self): 1042 self.check_itemconfigure('fg', '#110022') 1043 1044 def test_itemconfigure_foreground(self): 1045 self.check_itemconfigure('foreground', '#110022') 1046 1047 def test_itemconfigure_selectbackground(self): 1048 self.check_itemconfigure('selectbackground', '#110022') 1049 1050 def test_itemconfigure_selectforeground(self): 1051 self.check_itemconfigure('selectforeground', '#654321') 1052 1053 def test_box(self): 1054 lb = self.create() 1055 lb.insert(0, *('el%d' % i for i in range(8))) 1056 lb.pack() 1057 self.assertIsBoundingBox(lb.bbox(0)) 1058 self.assertIsNone(lb.bbox(-1)) 1059 self.assertIsNone(lb.bbox(10)) 1060 self.assertRaises(TclError, lb.bbox, 'noindex') 1061 self.assertRaises(TclError, lb.bbox, None) 1062 self.assertRaises(TypeError, lb.bbox) 1063 self.assertRaises(TypeError, lb.bbox, 0, 1) 1064 1065 def test_curselection(self): 1066 lb = self.create() 1067 lb.insert(0, *('el%d' % i for i in range(8))) 1068 lb.selection_clear(0, tkinter.END) 1069 lb.selection_set(2, 4) 1070 lb.selection_set(6) 1071 self.assertEqual(lb.curselection(), (2, 3, 4, 6)) 1072 self.assertRaises(TypeError, lb.curselection, 0) 1073 1074 def test_get(self): 1075 lb = self.create() 1076 lb.insert(0, *('el%d' % i for i in range(8))) 1077 self.assertEqual(lb.get(0), 'el0') 1078 self.assertEqual(lb.get(3), 'el3') 1079 self.assertEqual(lb.get('end'), 'el7') 1080 self.assertEqual(lb.get(8), '') 1081 self.assertEqual(lb.get(-1), '') 1082 self.assertEqual(lb.get(3, 5), ('el3', 'el4', 'el5')) 1083 self.assertEqual(lb.get(5, 'end'), ('el5', 'el6', 'el7')) 1084 self.assertEqual(lb.get(5, 0), ()) 1085 self.assertEqual(lb.get(0, 0), ('el0',)) 1086 self.assertRaises(TclError, lb.get, 'noindex') 1087 self.assertRaises(TclError, lb.get, None) 1088 self.assertRaises(TypeError, lb.get) 1089 self.assertRaises(TclError, lb.get, 'end', 'noindex') 1090 self.assertRaises(TypeError, lb.get, 1, 2, 3) 1091 self.assertRaises(TclError, lb.get, 2.4) 1092 1093 1094@add_standard_options(PixelSizeTests, StandardOptionsTests) 1095class ScaleTest(AbstractWidgetTest, unittest.TestCase): 1096 OPTIONS = ( 1097 'activebackground', 'background', 'bigincrement', 'borderwidth', 1098 'command', 'cursor', 'digits', 'font', 'foreground', 'from', 1099 'highlightbackground', 'highlightcolor', 'highlightthickness', 1100 'label', 'length', 'orient', 'relief', 1101 'repeatdelay', 'repeatinterval', 1102 'resolution', 'showvalue', 'sliderlength', 'sliderrelief', 'state', 1103 'takefocus', 'tickinterval', 'to', 'troughcolor', 'variable', 'width', 1104 ) 1105 default_orient = 'vertical' 1106 1107 def create(self, **kwargs): 1108 return tkinter.Scale(self.root, **kwargs) 1109 1110 def test_configure_bigincrement(self): 1111 widget = self.create() 1112 self.checkFloatParam(widget, 'bigincrement', 12.4, 23.6, -5) 1113 1114 def test_configure_digits(self): 1115 widget = self.create() 1116 self.checkIntegerParam(widget, 'digits', 5, 0) 1117 1118 def test_configure_from(self): 1119 widget = self.create() 1120 conv = float if get_tk_patchlevel(self.root) >= (8, 6, 10) else float_round 1121 self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=conv) 1122 1123 def test_configure_label(self): 1124 widget = self.create() 1125 self.checkParam(widget, 'label', 'any string') 1126 self.checkParam(widget, 'label', '') 1127 1128 def test_configure_length(self): 1129 widget = self.create() 1130 self.checkPixelsParam(widget, 'length', 130, 131.2, 135.6, '5i') 1131 1132 def test_configure_resolution(self): 1133 widget = self.create() 1134 self.checkFloatParam(widget, 'resolution', 4.2, 0, 6.7, -2) 1135 1136 def test_configure_showvalue(self): 1137 widget = self.create() 1138 self.checkBooleanParam(widget, 'showvalue') 1139 1140 def test_configure_sliderlength(self): 1141 widget = self.create() 1142 self.checkPixelsParam(widget, 'sliderlength', 1143 10, 11.2, 15.6, -3, '3m') 1144 1145 def test_configure_sliderrelief(self): 1146 widget = self.create() 1147 self.checkReliefParam(widget, 'sliderrelief') 1148 1149 def test_configure_tickinterval(self): 1150 widget = self.create() 1151 self.checkFloatParam(widget, 'tickinterval', 1, 4.3, 7.6, 0, 1152 conv=float_round) 1153 self.checkParam(widget, 'tickinterval', -2, expected=2, 1154 conv=float_round) 1155 1156 def test_configure_to(self): 1157 widget = self.create() 1158 self.checkFloatParam(widget, 'to', 300, 14.9, 15.1, -10, 1159 conv=float_round) 1160 1161 1162@add_standard_options(PixelSizeTests, StandardOptionsTests) 1163class ScrollbarTest(AbstractWidgetTest, unittest.TestCase): 1164 OPTIONS = ( 1165 'activebackground', 'activerelief', 1166 'background', 'borderwidth', 1167 'command', 'cursor', 'elementborderwidth', 1168 'highlightbackground', 'highlightcolor', 'highlightthickness', 1169 'jump', 'orient', 'relief', 1170 'repeatdelay', 'repeatinterval', 1171 'takefocus', 'troughcolor', 'width', 1172 ) 1173 _conv_pixels = round 1174 _stringify = True 1175 default_orient = 'vertical' 1176 1177 def create(self, **kwargs): 1178 return tkinter.Scrollbar(self.root, **kwargs) 1179 1180 def test_configure_elementborderwidth(self): 1181 widget = self.create() 1182 self.checkPixelsParam(widget, 'elementborderwidth', 4.3, 5.6, '1m') 1183 expected = self._default_pixels if tk_version >= (8, 7) else -2 1184 self.checkParam(widget, 'elementborderwidth', -2, expected=expected) 1185 1186 def test_configure_orient(self): 1187 widget = self.create() 1188 self.checkEnumParam(widget, 'orient', 'vertical', 'horizontal', 1189 fullname='orientation', allow_empty=True) 1190 1191 def test_activate(self): 1192 sb = self.create() 1193 for e in ('arrow1', 'slider', 'arrow2'): 1194 sb.activate(e) 1195 self.assertEqual(sb.activate(), e) 1196 sb.activate('') 1197 self.assertIsNone(sb.activate()) 1198 self.assertRaises(TypeError, sb.activate, 'arrow1', 'arrow2') 1199 1200 def test_set(self): 1201 sb = self.create() 1202 sb.set(0.2, 0.4) 1203 self.assertEqual(sb.get(), (0.2, 0.4)) 1204 self.assertRaises(TclError, sb.set, 'abc', 'def') 1205 self.assertRaises(TclError, sb.set, 0.6, 'def') 1206 self.assertRaises(TclError, sb.set, 0.6, None) 1207 self.assertRaises(TypeError, sb.set, 0.6) 1208 self.assertRaises(TypeError, sb.set, 0.6, 0.7, 0.8) 1209 1210 1211@add_standard_options(StandardOptionsTests) 1212class PanedWindowTest(AbstractWidgetTest, unittest.TestCase): 1213 OPTIONS = ( 1214 'background', 'borderwidth', 'cursor', 1215 'handlepad', 'handlesize', 'height', 1216 'opaqueresize', 'orient', 1217 'proxybackground', 'proxyborderwidth', 'proxyrelief', 1218 'relief', 1219 'sashcursor', 'sashpad', 'sashrelief', 'sashwidth', 1220 'showhandle', 'width', 1221 ) 1222 default_orient = 'horizontal' 1223 1224 def create(self, **kwargs): 1225 return tkinter.PanedWindow(self.root, **kwargs) 1226 1227 def test_configure_handlepad(self): 1228 widget = self.create() 1229 self.checkPixelsParam(widget, 'handlepad', 5, 6.4, 7.6, -3, '1m') 1230 1231 def test_configure_handlesize(self): 1232 widget = self.create() 1233 self.checkPixelsParam(widget, 'handlesize', 8, 9.4, 10.6, -3, '2m', 1234 conv=False) 1235 1236 def test_configure_height(self): 1237 widget = self.create() 1238 self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i', 1239 conv=False) 1240 1241 def test_configure_opaqueresize(self): 1242 widget = self.create() 1243 self.checkBooleanParam(widget, 'opaqueresize') 1244 1245 @requires_tk(8, 6, 5) 1246 def test_configure_proxybackground(self): 1247 widget = self.create() 1248 self.checkColorParam(widget, 'proxybackground') 1249 1250 @requires_tk(8, 6, 5) 1251 def test_configure_proxyborderwidth(self): 1252 widget = self.create() 1253 self.checkPixelsParam(widget, 'proxyborderwidth', 1254 0, 1.3, 2.9, 6, -2, '10p', 1255 conv=False) 1256 1257 @requires_tk(8, 6, 5) 1258 def test_configure_proxyrelief(self): 1259 widget = self.create() 1260 self.checkReliefParam(widget, 'proxyrelief', 1261 allow_empty=(tk_version >= (8, 7))) 1262 1263 def test_configure_sashcursor(self): 1264 widget = self.create() 1265 self.checkCursorParam(widget, 'sashcursor') 1266 1267 def test_configure_sashpad(self): 1268 widget = self.create() 1269 self.checkPixelsParam(widget, 'sashpad', 8, 1.3, 2.6, -2, '2m') 1270 1271 def test_configure_sashrelief(self): 1272 widget = self.create() 1273 self.checkReliefParam(widget, 'sashrelief') 1274 1275 def test_configure_sashwidth(self): 1276 widget = self.create() 1277 self.checkPixelsParam(widget, 'sashwidth', 10, 11.1, 15.6, -3, '1m', 1278 conv=False) 1279 1280 def test_configure_showhandle(self): 1281 widget = self.create() 1282 self.checkBooleanParam(widget, 'showhandle') 1283 1284 def test_configure_width(self): 1285 widget = self.create() 1286 self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i', 1287 conv=False) 1288 1289 def create2(self): 1290 p = self.create() 1291 b = tkinter.Button(p) 1292 c = tkinter.Button(p) 1293 p.add(b) 1294 p.add(c) 1295 return p, b, c 1296 1297 def test_paneconfigure(self): 1298 p, b, c = self.create2() 1299 self.assertRaises(TypeError, p.paneconfigure) 1300 d = p.paneconfigure(b) 1301 self.assertIsInstance(d, dict) 1302 for k, v in d.items(): 1303 self.assertEqual(len(v), 5) 1304 self.assertEqual(v, p.paneconfigure(b, k)) 1305 self.assertEqual(v[4], p.panecget(b, k)) 1306 1307 def check_paneconfigure(self, p, b, name, value, expected): 1308 if not self.wantobjects: 1309 expected = str(expected) 1310 p.paneconfigure(b, **{name: value}) 1311 self.assertEqual(p.paneconfigure(b, name)[4], expected) 1312 self.assertEqual(p.panecget(b, name), expected) 1313 1314 def check_paneconfigure_bad(self, p, b, name, msg): 1315 with self.assertRaisesRegex(TclError, msg): 1316 p.paneconfigure(b, **{name: 'badValue'}) 1317 1318 def test_paneconfigure_after(self): 1319 p, b, c = self.create2() 1320 self.check_paneconfigure(p, b, 'after', c, str(c)) 1321 self.check_paneconfigure_bad(p, b, 'after', 1322 'bad window path name "badValue"') 1323 1324 def test_paneconfigure_before(self): 1325 p, b, c = self.create2() 1326 self.check_paneconfigure(p, b, 'before', c, str(c)) 1327 self.check_paneconfigure_bad(p, b, 'before', 1328 'bad window path name "badValue"') 1329 1330 def test_paneconfigure_height(self): 1331 p, b, c = self.create2() 1332 self.check_paneconfigure(p, b, 'height', 10, 10) 1333 self.check_paneconfigure_bad(p, b, 'height', 1334 EXPECTED_SCREEN_DISTANCE_OR_EMPTY_ERRMSG.format('badValue')) 1335 1336 def test_paneconfigure_hide(self): 1337 p, b, c = self.create2() 1338 self.check_paneconfigure(p, b, 'hide', False, 0) 1339 self.check_paneconfigure_bad(p, b, 'hide', 1340 'expected boolean value but got "badValue"') 1341 1342 def test_paneconfigure_minsize(self): 1343 p, b, c = self.create2() 1344 self.check_paneconfigure(p, b, 'minsize', 10, 10) 1345 self.check_paneconfigure_bad(p, b, 'minsize', 1346 EXPECTED_SCREEN_DISTANCE_ERRMSG.format('badValue')) 1347 1348 def test_paneconfigure_padx(self): 1349 p, b, c = self.create2() 1350 self.check_paneconfigure(p, b, 'padx', 1.3, 1) 1351 self.check_paneconfigure_bad(p, b, 'padx', 1352 EXPECTED_SCREEN_DISTANCE_ERRMSG.format('badValue')) 1353 1354 def test_paneconfigure_pady(self): 1355 p, b, c = self.create2() 1356 self.check_paneconfigure(p, b, 'pady', 1.3, 1) 1357 self.check_paneconfigure_bad(p, b, 'pady', 1358 EXPECTED_SCREEN_DISTANCE_ERRMSG.format('badValue')) 1359 1360 def test_paneconfigure_sticky(self): 1361 p, b, c = self.create2() 1362 self.check_paneconfigure(p, b, 'sticky', 'nsew', 'nesw') 1363 self.check_paneconfigure_bad(p, b, 'sticky', 1364 'bad stickyness value "badValue": must ' 1365 'be a string containing zero or more of ' 1366 'n, e, s, and w') 1367 1368 def test_paneconfigure_stretch(self): 1369 p, b, c = self.create2() 1370 self.check_paneconfigure(p, b, 'stretch', 'alw', 'always') 1371 self.check_paneconfigure_bad(p, b, 'stretch', 1372 'bad stretch "badValue": must be ' 1373 'always, first, last, middle, or never') 1374 1375 def test_paneconfigure_width(self): 1376 p, b, c = self.create2() 1377 self.check_paneconfigure(p, b, 'width', 10, 10) 1378 self.check_paneconfigure_bad(p, b, 'width', 1379 EXPECTED_SCREEN_DISTANCE_OR_EMPTY_ERRMSG.format('badValue')) 1380 1381 1382@add_standard_options(StandardOptionsTests) 1383class MenuTest(AbstractWidgetTest, unittest.TestCase): 1384 OPTIONS = ( 1385 'activebackground', 'activeborderwidth', 'activeforeground', 1386 'activerelief', 1387 'background', 'borderwidth', 'cursor', 1388 'disabledforeground', 'font', 'foreground', 1389 'postcommand', 'relief', 'selectcolor', 'takefocus', 1390 'tearoff', 'tearoffcommand', 'title', 'type', 1391 ) 1392 _conv_pixels = False 1393 1394 def create(self, **kwargs): 1395 return tkinter.Menu(self.root, **kwargs) 1396 1397 def test_indexcommand_none(self): 1398 widget = self.create() 1399 i = widget.index('none') 1400 self.assertIsNone(i) 1401 1402 test_configure_activerelief = requires_tk(8, 7)(StandardOptionsTests.test_configure_activerelief) 1403 1404 def test_configure_postcommand(self): 1405 widget = self.create() 1406 self.checkCommandParam(widget, 'postcommand') 1407 1408 def test_configure_tearoff(self): 1409 widget = self.create() 1410 self.checkBooleanParam(widget, 'tearoff') 1411 1412 def test_configure_tearoffcommand(self): 1413 widget = self.create() 1414 self.checkCommandParam(widget, 'tearoffcommand') 1415 1416 def test_configure_title(self): 1417 widget = self.create() 1418 self.checkParam(widget, 'title', 'any string') 1419 1420 def test_configure_type(self): 1421 widget = self.create() 1422 values = ('normal', 'tearoff', 'menubar') 1423 self.checkEnumParam(widget, 'type', *values, 1424 allow_empty=tk_version < (8, 7), 1425 sort=tk_version >= (8, 7)) 1426 1427 def test_entryconfigure(self): 1428 m1 = self.create() 1429 m1.add_command(label='test') 1430 self.assertRaises(TypeError, m1.entryconfigure) 1431 with self.assertRaisesRegex(TclError, 'bad menu entry index "foo"'): 1432 m1.entryconfigure('foo') 1433 d = m1.entryconfigure(1) 1434 self.assertIsInstance(d, dict) 1435 for k, v in d.items(): 1436 self.assertIsInstance(k, str) 1437 self.assertIsInstance(v, tuple) 1438 self.assertEqual(len(v), 5) 1439 self.assertEqual(v[0], k) 1440 self.assertEqual(m1.entrycget(1, k), v[4]) 1441 m1.destroy() 1442 1443 def test_entryconfigure_label(self): 1444 m1 = self.create() 1445 m1.add_command(label='test') 1446 self.assertEqual(m1.entrycget(1, 'label'), 'test') 1447 m1.entryconfigure(1, label='changed') 1448 self.assertEqual(m1.entrycget(1, 'label'), 'changed') 1449 1450 def test_entryconfigure_variable(self): 1451 m1 = self.create() 1452 v1 = tkinter.BooleanVar(self.root) 1453 v2 = tkinter.BooleanVar(self.root) 1454 m1.add_checkbutton(variable=v1, onvalue=True, offvalue=False, 1455 label='Nonsense') 1456 self.assertEqual(str(m1.entrycget(1, 'variable')), str(v1)) 1457 m1.entryconfigure(1, variable=v2) 1458 self.assertEqual(str(m1.entrycget(1, 'variable')), str(v2)) 1459 1460 1461@add_standard_options(PixelSizeTests, StandardOptionsTests) 1462class MessageTest(AbstractWidgetTest, unittest.TestCase): 1463 OPTIONS = ( 1464 'anchor', 'aspect', 'background', 'borderwidth', 1465 'cursor', 'font', 'foreground', 1466 'highlightbackground', 'highlightcolor', 'highlightthickness', 1467 'justify', 'padx', 'pady', 'relief', 1468 'takefocus', 'text', 'textvariable', 'width', 1469 ) 1470 _conv_pad_pixels = False 1471 if tk_version >= (8, 7): 1472 _conv_pixels = False 1473 _clip_pad = tk_version >= (8, 7) 1474 _clip_borderwidth = tk_version >= (8, 7) 1475 1476 def create(self, **kwargs): 1477 return tkinter.Message(self.root, **kwargs) 1478 1479 def test_configure_aspect(self): 1480 widget = self.create() 1481 self.checkIntegerParam(widget, 'aspect', 250, 0, -300) 1482 1483 def test_configure_padx(self): 1484 widget = self.create() 1485 self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m', 1486 conv=self._conv_pad_pixels) 1487 expected = self._default_pixels if self._clip_pad else -2 1488 self.checkParam(widget, 'padx', -2, expected=expected) 1489 1490 def test_configure_pady(self): 1491 widget = self.create() 1492 self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m', 1493 conv=self._conv_pad_pixels) 1494 expected = self._default_pixels if self._clip_pad else -2 1495 self.checkParam(widget, 'pady', -2, expected=expected) 1496 1497 def test_configure_width(self): 1498 widget = self.create() 1499 self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, 0, '5i') 1500 expected = 0 if tk_version >= (8, 7) else -402 1501 self.checkParam(widget, 'width', -402, expected=expected) 1502 1503 1504class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): 1505 1506 def test_frame(self): 1507 self._test_widget(tkinter.Frame) 1508 1509 def test_label(self): 1510 self._test_widget(tkinter.Label) 1511 1512 1513if __name__ == '__main__': 1514 unittest.main() 1515