python (3.12.0)

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