https://github.com/python/cpython/commit/87a349e3d4f29e9ca8d69c14d5f54c30c9c631a0
commit: 87a349e3d4f29e9ca8d69c14d5f54c30c9c631a0
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-06-20T01:27:27+03:00
summary:

[3.13] gh-151678: Add tests for tkinter.ttk methods (GH-151736) (GH-151743)

Cover previously-untested ttk methods:

* Progressbar.step, start and stop;
* Treeview.parent, next, prev, see and identify_element;
* Style.theme_settings;
* OptionMenu.set_menu.
(cherry picked from commit 7d4a0aad7be3cfb367b8977a03a64e754577d5f0)

Co-authored-by: Serhiy Storchaka <[email protected]>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>

* Fix regex in tests.

---------

Co-authored-by: Serhiy Storchaka <[email protected]>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>

files:
M Lib/test/test_ttk/test_extensions.py
M Lib/test/test_ttk/test_style.py
M Lib/test/test_ttk/test_widgets.py

diff --git a/Lib/test/test_ttk/test_extensions.py 
b/Lib/test/test_ttk/test_extensions.py
index 9688d94f07727a4..4ecd0c233afdd76 100644
--- a/Lib/test/test_ttk/test_extensions.py
+++ b/Lib/test/test_ttk/test_extensions.py
@@ -281,6 +281,24 @@ def cb_test(item):
 
         optmenu.destroy()
 
+    def test_set_menu(self):
+        optmenu = ttk.OptionMenu(self.root, self.textvar, 'a', 'a', 'b', 'c')
+        menu = optmenu['menu']
+        self.assertEqual(menu.index('end'), 2)
+
+        # set_menu rebuilds the menu with new values and an optional default.
+        optmenu.set_menu('y', 'x', 'y', 'z')
+        self.assertEqual(self.textvar.get(), 'y')
+        self.assertEqual([menu.entrycget(i, 'label') for i in range(3)],
+                         ['x', 'y', 'z'])
+
+        # Without a default the variable is left unchanged.
+        optmenu.set_menu(None, 'p', 'q')
+        self.assertEqual(self.textvar.get(), 'y')
+        self.assertEqual([menu.entrycget(i, 'label') for i in range(2)],
+                         ['p', 'q'])
+        optmenu.destroy()
+
     def test_unique_radiobuttons(self):
         # check that radiobuttons are unique across instances (bpo25684)
         items = ('a', 'b', 'c')
diff --git a/Lib/test/test_ttk/test_style.py b/Lib/test/test_ttk/test_style.py
index 46365a135149065..0a54abb0f51a291 100644
--- a/Lib/test/test_ttk/test_style.py
+++ b/Lib/test/test_ttk/test_style.py
@@ -124,6 +124,22 @@ def test_theme_use(self):
 
         self.style.theme_use(curr_theme)
 
+    def test_theme_settings(self):
+        style = self.style
+        theme = style.theme_use()
+        style.theme_settings(theme, {
+            'Test.TLabel': {
+                'configure': {'foreground': 'red', 'background': 'blue'},
+                'map': {'foreground': [('active', 'green')]},
+            },
+        })
+        self.assertEqual(style.lookup('Test.TLabel', 'foreground'), 'red')
+        self.assertEqual(style.lookup('Test.TLabel', 'background'), 'blue')
+        self.assertEqual(style.map('Test.TLabel', 'foreground'),
+                         [('active', 'green')])
+        self.assertRaises(tkinter.TclError, style.theme_settings,
+                          'nonexistingname', {})
+
     def test_configure_custom_copy(self):
         style = self.style
 
diff --git a/Lib/test/test_ttk/test_widgets.py 
b/Lib/test/test_ttk/test_widgets.py
index f7c0e2e7c87bc08..5758298e8fe362e 100644
--- a/Lib/test/test_ttk/test_widgets.py
+++ b/Lib/test/test_ttk/test_widgets.py
@@ -950,6 +950,27 @@ def test_configure_value(self):
 
     test_configure_wraplength = requires_tk(8, 
7)(StandardOptionsTests.test_configure_wraplength)
 
+    def test_step(self):
+        widget = self.create(maximum=100, mode='determinate')
+        self.assertEqual(float(widget['value']), 0.0)
+        widget.step()  # The default increment is 1.0.
+        self.assertEqual(float(widget['value']), 1.0)
+        widget.step(5)
+        self.assertEqual(float(widget['value']), 6.0)
+        widget.step(-2)
+        self.assertEqual(float(widget['value']), 4.0)
+
+    def test_start_stop(self):
+        widget = self.create(maximum=100, mode='determinate')
+        widget.pack()
+        widget.start()  # Schedule autoincrement; no exception.
+        widget.update()
+        widget.stop()   # Cancel it.
+        # After stopping, the value no longer changes.
+        value = float(widget['value'])
+        widget.update()
+        self.assertEqual(float(widget['value']), value)
+
 
 @unittest.skipIf(sys.platform == 'darwin',
                  'ttk.Scrollbar is special on MacOSX')
@@ -1604,6 +1625,50 @@ def test_exists(self):
         # in the tcl interpreter since tk requires an item.
         self.assertRaises(tkinter.TclError, self.tv.exists, None)
 
+    def test_parent(self):
+        a = self.tv.insert('', 'end')
+        b = self.tv.insert(a, 'end')
+        self.assertEqual(self.tv.parent(b), a)
+        self.assertEqual(self.tv.parent(a), '')
+        self.assertRaises(tkinter.TclError, self.tv.parent, 'nonexistent')
+
+    def test_next_prev(self):
+        a = self.tv.insert('', 'end')
+        b = self.tv.insert('', 'end')
+        c = self.tv.insert('', 'end')
+        self.assertEqual(self.tv.next(a), b)
+        self.assertEqual(self.tv.next(b), c)
+        self.assertEqual(self.tv.next(c), '')
+        self.assertEqual(self.tv.prev(c), b)
+        self.assertEqual(self.tv.prev(b), a)
+        self.assertEqual(self.tv.prev(a), '')
+        self.assertRaises(tkinter.TclError, self.tv.next, 'nonexistent')
+        self.assertRaises(tkinter.TclError, self.tv.prev, 'nonexistent')
+
+    def test_see(self):
+        a = self.tv.insert('', 'end')
+        b = self.tv.insert(a, 'end')
+        # see() opens all of the item's ancestors.
+        self.assertFalse(self.tv.tk.getboolean(self.tv.item(a, 'open')))
+        self.tv.see(b)
+        self.assertTrue(self.tv.tk.getboolean(self.tv.item(a, 'open')))
+        self.assertRaises(tkinter.TclError, self.tv.see, 'nonexistent')
+
+    def test_identify_element(self):
+        self.tv.pack()
+        self.tv.wait_visibility()
+        parent = self.tv.insert('', 'end', text='parent')
+        self.tv.insert(parent, 'end', text='child')
+        self.tv.update()
+        x, y, w, h = self.tv.bbox(parent)
+        # The Treeitem.indicator element is packed at the left of the row in
+        # the Item layout on every platform and theme.
+        element = self.tv.identify_element(x + 8, y + h // 2)
+        self.assertRegex(element, r'.*indicator\Z')
+        # The empty string is returned outside the widget.
+        self.assertEqual(self.tv.identify_element(-1, -1), '')
+        self.assertRaises(tkinter.TclError, self.tv.identify_element, None, 5)
+
     def test_focus(self):
         # nothing is focused right now
         self.assertEqual(self.tv.focus(), '')

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to