summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/tkinter/__init__.py5
-rw-r--r--Lib/tkinter/test/test_tkinter/test_geometry_managers.py6
-rw-r--r--Lib/tkinter/test/test_tkinter/test_widgets.py13
-rw-r--r--Lib/tkinter/test/test_ttk/test_widgets.py268
-rw-r--r--Lib/tkinter/test/widget_tests.py27
-rw-r--r--Misc/NEWS2
6 files changed, 183 insertions, 138 deletions
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 4e642c6..8139e38 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -1337,8 +1337,9 @@ class Misc:
self.configure({key: value})
def keys(self):
"""Return a list of all resource names of this widget."""
- return [x[0][1:] for x in
- self.tk.splitlist(self.tk.call(self._w, 'configure'))]
+ splitlist = self.tk.splitlist
+ return [splitlist(x)[0][1:] for x in
+ splitlist(self.tk.call(self._w, 'configure'))]
def __str__(self):
"""Return the window path name of this widget."""
return self._w
diff --git a/Lib/tkinter/test/test_tkinter/test_geometry_managers.py b/Lib/tkinter/test/test_tkinter/test_geometry_managers.py
index e42b1be..c645d43 100644
--- a/Lib/tkinter/test/test_tkinter/test_geometry_managers.py
+++ b/Lib/tkinter/test/test_tkinter/test_geometry_managers.py
@@ -12,6 +12,8 @@ requires('gui')
class PackTest(AbstractWidgetTest, unittest.TestCase):
+ test_keys = None
+
def create2(self):
pack = tkinter.Toplevel(self.root, name='pack')
pack.wm_geometry('300x200+0+0')
@@ -276,6 +278,8 @@ class PackTest(AbstractWidgetTest, unittest.TestCase):
class PlaceTest(AbstractWidgetTest, unittest.TestCase):
+ test_keys = None
+
def create2(self):
t = tkinter.Toplevel(self.root, width=300, height=200, bd=0)
t.wm_geometry('300x200+0+0')
@@ -478,6 +482,8 @@ class PlaceTest(AbstractWidgetTest, unittest.TestCase):
class GridTest(AbstractWidgetTest, unittest.TestCase):
+ test_keys = None
+
def tearDown(self):
cols, rows = self.root.grid_size()
for i in range(cols + 1):
diff --git a/Lib/tkinter/test/test_tkinter/test_widgets.py b/Lib/tkinter/test/test_tkinter/test_widgets.py
index 7171667..c924d55 100644
--- a/Lib/tkinter/test/test_tkinter/test_widgets.py
+++ b/Lib/tkinter/test/test_tkinter/test_widgets.py
@@ -102,7 +102,7 @@ class FrameTest(AbstractToplevelTest, unittest.TestCase):
'background', 'borderwidth',
'class', 'colormap', 'container', 'cursor', 'height',
'highlightbackground', 'highlightcolor', 'highlightthickness',
- 'relief', 'takefocus', 'visual', 'width',
+ 'padx', 'pady', 'relief', 'takefocus', 'visual', 'width',
)
def create(self, **kwargs):
@@ -636,7 +636,7 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase):
'highlightbackground', 'highlightcolor', 'highlightthickness',
'insertbackground', 'insertborderwidth',
'insertofftime', 'insertontime', 'insertwidth',
- 'relief', 'scrollregion',
+ 'offset', 'relief', 'scrollregion',
'selectbackground', 'selectborderwidth', 'selectforeground',
'state', 'takefocus',
'xscrollcommand', 'xscrollincrement',
@@ -658,6 +658,15 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase):
widget = self.create()
self.checkBooleanParam(widget, 'confine')
+ def test_offset(self):
+ widget = self.create()
+ self.assertEqual(widget['offset'], '0,0')
+ self.checkParams(widget, 'offset',
+ 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'center')
+ self.checkParam(widget, 'offset', '10,20')
+ self.checkParam(widget, 'offset', '#5,6')
+ self.checkInvalidParam(widget, 'offset', 'spam')
+
def test_scrollregion(self):
widget = self.create()
self.checkParam(widget, 'scrollregion', '0 0 200 150')
diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py
index afd3230..c031351 100644
--- a/Lib/tkinter/test/test_ttk/test_widgets.py
+++ b/Lib/tkinter/test/test_ttk/test_widgets.py
@@ -187,7 +187,7 @@ class AbstractLabelTest(AbstractWidgetTest):
@add_standard_options(StandardTtkOptionsTests)
class LabelTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = (
- 'anchor', 'background',
+ 'anchor', 'background', 'borderwidth',
'class', 'compound', 'cursor', 'font', 'foreground',
'image', 'justify', 'padding', 'relief', 'state', 'style',
'takefocus', 'text', 'textvariable',
@@ -208,7 +208,8 @@ class LabelTest(AbstractLabelTest, unittest.TestCase):
class ButtonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = (
'class', 'command', 'compound', 'cursor', 'default',
- 'image', 'state', 'style', 'takefocus', 'text', 'textvariable',
+ 'image', 'padding', 'state', 'style',
+ 'takefocus', 'text', 'textvariable',
'underline', 'width',
)
@@ -232,7 +233,7 @@ class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
'class', 'command', 'compound', 'cursor',
'image',
'offvalue', 'onvalue',
- 'state', 'style',
+ 'padding', 'state', 'style',
'takefocus', 'text', 'textvariable',
'underline', 'variable', 'width',
)
@@ -276,137 +277,10 @@ class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
-class ComboboxTest(AbstractWidgetTest, unittest.TestCase):
- OPTIONS = (
- 'class', 'cursor', 'exportselection', 'height',
- 'justify', 'postcommand', 'state', 'style',
- 'takefocus', 'textvariable', 'values', 'width',
- )
-
- def setUp(self):
- super().setUp()
- self.combo = self.create()
-
- def create(self, **kwargs):
- return ttk.Combobox(self.root, **kwargs)
-
- def test_height(self):
- widget = self.create()
- self.checkParams(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i')
-
- def test_state(self):
- widget = self.create()
- self.checkParams(widget, 'state', 'active', 'disabled', 'normal')
-
- def _show_drop_down_listbox(self):
- width = self.combo.winfo_width()
- self.combo.event_generate('<ButtonPress-1>', x=width - 5, y=5)
- self.combo.event_generate('<ButtonRelease-1>', x=width - 5, y=5)
- self.combo.update_idletasks()
-
-
- def test_virtual_event(self):
- success = []
-
- self.combo['values'] = [1]
- self.combo.bind('<<ComboboxSelected>>',
- lambda evt: success.append(True))
- self.combo.pack()
- self.combo.wait_visibility()
-
- height = self.combo.winfo_height()
- self._show_drop_down_listbox()
- self.combo.update()
- self.combo.event_generate('<Return>')
- self.combo.update()
-
- self.assertTrue(success)
-
-
- def test_postcommand(self):
- success = []
-
- self.combo['postcommand'] = lambda: success.append(True)
- self.combo.pack()
- self.combo.wait_visibility()
-
- self._show_drop_down_listbox()
- self.assertTrue(success)
-
- # testing postcommand removal
- self.combo['postcommand'] = ''
- self._show_drop_down_listbox()
- self.assertEqual(len(success), 1)
-
-
- def test_values(self):
- def check_get_current(getval, currval):
- self.assertEqual(self.combo.get(), getval)
- self.assertEqual(self.combo.current(), currval)
-
- self.assertEqual(self.combo['values'],
- () if tcl_version < (8, 5) else '')
- check_get_current('', -1)
-
- self.checkParam(self.combo, 'values', 'mon tue wed thur',
- expected=('mon', 'tue', 'wed', 'thur'))
- self.checkParam(self.combo, 'values', ('mon', 'tue', 'wed', 'thur'))
- self.checkParam(self.combo, 'values', (42, 3.14, '', 'any string'))
- self.checkParam(self.combo, 'values', '',
- expected='' if get_tk_patchlevel() < (8, 5, 10) else ())
-
- self.combo['values'] = ['a', 1, 'c']
-
- self.combo.set('c')
- check_get_current('c', 2)
-
- self.combo.current(0)
- check_get_current('a', 0)
-
- self.combo.set('d')
- check_get_current('d', -1)
-
- # testing values with empty string
- self.combo.set('')
- self.combo['values'] = (1, 2, '', 3)
- check_get_current('', 2)
-
- # testing values with empty string set through configure
- self.combo.configure(values=[1, '', 2])
- self.assertEqual(self.combo['values'],
- ('1', '', '2') if self.wantobjects else
- '1 {} 2')
-
- # testing values with spaces
- self.combo['values'] = ['a b', 'a\tb', 'a\nb']
- self.assertEqual(self.combo['values'],
- ('a b', 'a\tb', 'a\nb') if self.wantobjects else
- '{a b} {a\tb} {a\nb}')
-
- # testing values with special characters
- self.combo['values'] = [r'a\tb', '"a"', '} {']
- self.assertEqual(self.combo['values'],
- (r'a\tb', '"a"', '} {') if self.wantobjects else
- r'a\\tb {"a"} \}\ \{')
-
- # out of range
- self.assertRaises(tkinter.TclError, self.combo.current,
- len(self.combo['values']))
- # it expects an integer (or something that can be converted to int)
- self.assertRaises(tkinter.TclError, self.combo.current, '')
-
- # testing creating combobox with empty string in values
- combo2 = ttk.Combobox(self.root, values=[1, 2, ''])
- self.assertEqual(combo2['values'],
- ('1', '2', '') if self.wantobjects else '1 2 {}')
- combo2.destroy()
-
-
-@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
class EntryTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = (
'background', 'class', 'cursor',
- 'exportselection', 'font',
+ 'exportselection', 'font', 'foreground',
'invalidcommand', 'justify',
'show', 'state', 'style', 'takefocus', 'textvariable',
'validate', 'validatecommand', 'width', 'xscrollcommand',
@@ -535,6 +409,132 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
+class ComboboxTest(EntryTest, unittest.TestCase):
+ OPTIONS = (
+ 'background', 'class', 'cursor', 'exportselection',
+ 'font', 'foreground', 'height', 'invalidcommand',
+ 'justify', 'postcommand', 'show', 'state', 'style',
+ 'takefocus', 'textvariable',
+ 'validate', 'validatecommand', 'values',
+ 'width', 'xscrollcommand',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.combo = self.create()
+
+ def create(self, **kwargs):
+ return ttk.Combobox(self.root, **kwargs)
+
+ def test_height(self):
+ widget = self.create()
+ self.checkParams(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i')
+
+ def _show_drop_down_listbox(self):
+ width = self.combo.winfo_width()
+ self.combo.event_generate('<ButtonPress-1>', x=width - 5, y=5)
+ self.combo.event_generate('<ButtonRelease-1>', x=width - 5, y=5)
+ self.combo.update_idletasks()
+
+
+ def test_virtual_event(self):
+ success = []
+
+ self.combo['values'] = [1]
+ self.combo.bind('<<ComboboxSelected>>',
+ lambda evt: success.append(True))
+ self.combo.pack()
+ self.combo.wait_visibility()
+
+ height = self.combo.winfo_height()
+ self._show_drop_down_listbox()
+ self.combo.update()
+ self.combo.event_generate('<Return>')
+ self.combo.update()
+
+ self.assertTrue(success)
+
+
+ def test_postcommand(self):
+ success = []
+
+ self.combo['postcommand'] = lambda: success.append(True)
+ self.combo.pack()
+ self.combo.wait_visibility()
+
+ self._show_drop_down_listbox()
+ self.assertTrue(success)
+
+ # testing postcommand removal
+ self.combo['postcommand'] = ''
+ self._show_drop_down_listbox()
+ self.assertEqual(len(success), 1)
+
+
+ def test_values(self):
+ def check_get_current(getval, currval):
+ self.assertEqual(self.combo.get(), getval)
+ self.assertEqual(self.combo.current(), currval)
+
+ self.assertEqual(self.combo['values'],
+ () if tcl_version < (8, 5) else '')
+ check_get_current('', -1)
+
+ self.checkParam(self.combo, 'values', 'mon tue wed thur',
+ expected=('mon', 'tue', 'wed', 'thur'))
+ self.checkParam(self.combo, 'values', ('mon', 'tue', 'wed', 'thur'))
+ self.checkParam(self.combo, 'values', (42, 3.14, '', 'any string'))
+ self.checkParam(self.combo, 'values', '',
+ expected='' if get_tk_patchlevel() < (8, 5, 10) else ())
+
+ self.combo['values'] = ['a', 1, 'c']
+
+ self.combo.set('c')
+ check_get_current('c', 2)
+
+ self.combo.current(0)
+ check_get_current('a', 0)
+
+ self.combo.set('d')
+ check_get_current('d', -1)
+
+ # testing values with empty string
+ self.combo.set('')
+ self.combo['values'] = (1, 2, '', 3)
+ check_get_current('', 2)
+
+ # testing values with empty string set through configure
+ self.combo.configure(values=[1, '', 2])
+ self.assertEqual(self.combo['values'],
+ ('1', '', '2') if self.wantobjects else
+ '1 {} 2')
+
+ # testing values with spaces
+ self.combo['values'] = ['a b', 'a\tb', 'a\nb']
+ self.assertEqual(self.combo['values'],
+ ('a b', 'a\tb', 'a\nb') if self.wantobjects else
+ '{a b} {a\tb} {a\nb}')
+
+ # testing values with special characters
+ self.combo['values'] = [r'a\tb', '"a"', '} {']
+ self.assertEqual(self.combo['values'],
+ (r'a\tb', '"a"', '} {') if self.wantobjects else
+ r'a\\tb {"a"} \}\ \{')
+
+ # out of range
+ self.assertRaises(tkinter.TclError, self.combo.current,
+ len(self.combo['values']))
+ # it expects an integer (or something that can be converted to int)
+ self.assertRaises(tkinter.TclError, self.combo.current, '')
+
+ # testing creating combobox with empty string in values
+ combo2 = ttk.Combobox(self.root, values=[1, 2, ''])
+ self.assertEqual(combo2['values'],
+ ('1', '2', '') if self.wantobjects else '1 2 {}')
+ combo2.destroy()
+
+
+@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = (
'class', 'cursor', 'height',
@@ -674,7 +674,7 @@ class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = (
'class', 'command', 'compound', 'cursor',
'image',
- 'state', 'style',
+ 'padding', 'state', 'style',
'takefocus', 'text', 'textvariable',
'underline', 'value', 'variable', 'width',
)
@@ -724,7 +724,7 @@ class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = (
'class', 'compound', 'cursor', 'direction',
- 'image', 'menu', 'state', 'style',
+ 'image', 'menu', 'padding', 'state', 'style',
'takefocus', 'text', 'textvariable',
'underline', 'width',
)
@@ -902,7 +902,7 @@ class ScrollbarTest(AbstractWidgetTest, unittest.TestCase):
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
class NotebookTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = (
- 'class', 'cursor', 'height', 'padding', 'style', 'takefocus',
+ 'class', 'cursor', 'height', 'padding', 'style', 'takefocus', 'width',
)
def setUp(self):
diff --git a/Lib/tkinter/test/widget_tests.py b/Lib/tkinter/test/widget_tests.py
index 779538d..75a068f 100644
--- a/Lib/tkinter/test/widget_tests.py
+++ b/Lib/tkinter/test/widget_tests.py
@@ -206,6 +206,33 @@ class AbstractWidgetTest(AbstractTkTest):
break
+ def test_keys(self):
+ widget = self.create()
+ keys = widget.keys()
+ # XXX
+ if not isinstance(widget, Scale):
+ self.assertEqual(sorted(keys), sorted(widget.configure()))
+ for k in keys:
+ widget[k]
+ # Test if OPTIONS contains all keys
+ if test.support.verbose:
+ aliases = {
+ 'bd': 'borderwidth',
+ 'bg': 'background',
+ 'fg': 'foreground',
+ 'invcmd': 'invalidcommand',
+ 'vcmd': 'validatecommand',
+ }
+ keys = set(keys)
+ expected = set(self.OPTIONS)
+ for k in sorted(keys - expected):
+ if not (k in aliases and
+ aliases[k] in keys and
+ aliases[k] in expected):
+ print('%s.OPTIONS doesn\'t contain "%s"' %
+ (self.__class__.__name__, k))
+
+
class StandardOptionsTests:
STANDARD_OPTIONS = (
'activebackground', 'activeborderwidth', 'activeforeground', 'anchor',
diff --git a/Misc/NEWS b/Misc/NEWS
index 28674b8..b964181 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -91,6 +91,8 @@ Core and Builtins
Library
-------
+- Issue #26177: Fixed the keys() method for Canvas and Scrollbar widgets.
+
- Issue #15068: Got rid of excessive buffering in the fileinput module.
The bufsize parameter is no longer used.