https://github.com/python/cpython/commit/c42f36ac53c9f54c182d70fabe243a04934a8363 commit: c42f36ac53c9f54c182d70fabe243a04934a8363 branch: main author: Serhiy Storchaka <[email protected]> committer: serhiy-storchaka <[email protected]> date: 2026-06-22T12:52:50Z summary:
gh-151878: Add tkinter Entry and Spinbox validate methods (GH-151879) Wrap the Tk "validate" widget command of the entry and spinbox widgets as the methods Entry.validate() and Spinbox.validate(), forcing an evaluation of the validatecommand independently of the validate option and returning whether the value is valid. Co-authored-by: Claude Opus 4.8 <[email protected]> files: A Misc/NEWS.d/next/Library/2026-06-22-01-02-33.gh-issue-151878.IFIA5C.rst M Doc/library/tkinter.rst M Doc/whatsnew/3.16.rst M Lib/test/test_tkinter/test_widgets.py M Lib/tkinter/__init__.py diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index 249b1602a711ad..13fe3514b5ebc8 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -4254,6 +4254,14 @@ Widget classes Typically associated with mouse motion events, to produce the effect of dragging the entry at high speed through the window. + .. method:: validate() + + Force an evaluation of the command given by the *validatecommand* option, + independently of the conditions specified by the *validate* option, and + return whether the value is considered valid. + + .. versionadded:: next + .. class:: Frame(master=None, cnf={}, **kw) @@ -5206,6 +5214,14 @@ Widget classes .. versionadded:: 3.8 + .. method:: validate() + + Force an evaluation of the command given by the *validatecommand* option, + independently of the conditions specified by the *validate* option, and + return whether the value is considered valid. + + .. versionadded:: next + .. class:: Text(master=None, cnf={}, **kw) diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 8abc4d0af8d19f..3c625801c46a1c 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -163,6 +163,11 @@ tkinter synchronization of the displayed view with the underlying text. (Contributed by Serhiy Storchaka in :gh:`151675`.) +* Added a :meth:`!validate` method to the :class:`!tkinter.Entry` and + :class:`!tkinter.Spinbox` widgets, which forces an evaluation of the + validation command. + (Contributed by Serhiy Storchaka in :gh:`151878`.) + * Added new window-management methods :meth:`~tkinter.Misc.winfo_isdark` (dark mode detection), :meth:`~tkinter.Wm.wm_iconbadge` (application icon badge) and :meth:`~tkinter.Wm.wm_stackorder` (toplevel stacking order). diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index 4b51d219d87e5b..d0305562a0cb05 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -589,6 +589,25 @@ def test_select_aliases(self): self.assertRaisesRegex(TclError, 'bad entry index "xyz"', widget.select_range, 'xyz', 'end') + def test_validate(self): + calls = [] + def validatecommand(value): + calls.append(value) + return value.isdigit() + # validate='none' means validation is never triggered automatically, + # so validate() exercises the forced evaluation. + widget = self.create(validate='none', + validatecommand=(self.root.register(validatecommand), '%P')) + widget.insert(0, '123') + result = widget.validate() + self.assertIs(result, True) + self.assertEqual(calls, ['123']) + widget.delete(0, 'end') + widget.insert(0, 'abc') + calls.clear() + self.assertIs(widget.validate(), False) + self.assertEqual(calls, ['abc']) + @add_configure_tests(StandardOptionsTests) class SpinboxTest(EntryTest, unittest.TestCase): diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index 68de4a35689691..974e386be1bb49 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -3445,6 +3445,14 @@ def selection_to(self, index): select_to = selection_to + def validate(self): + """Force an evaluation of the validation command. + + This evaluates the command given by the validatecommand option, + independently of the conditions specified by the validate option. + Return whether the value is considered valid.""" + return self.tk.getboolean(self.tk.call(self._w, 'validate')) + class Frame(Widget): """Frame widget which may contain other widgets and can have a 3D border.""" @@ -4957,6 +4965,14 @@ def selection_to(self, index): """Set the variable end of a selection to INDEX.""" self.selection('to', index) + def validate(self): + """Force an evaluation of the validation command. + + This evaluates the command given by the validatecommand option, + independently of the conditions specified by the validate option. + Return whether the value is considered valid.""" + return self.tk.getboolean(self.tk.call(self._w, 'validate')) + ########################################################################### diff --git a/Misc/NEWS.d/next/Library/2026-06-22-01-02-33.gh-issue-151878.IFIA5C.rst b/Misc/NEWS.d/next/Library/2026-06-22-01-02-33.gh-issue-151878.IFIA5C.rst new file mode 100644 index 00000000000000..af0d2c25136c45 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-22-01-02-33.gh-issue-151878.IFIA5C.rst @@ -0,0 +1,3 @@ +Add the :meth:`!validate` method to the :class:`tkinter.Entry` and +:class:`tkinter.Spinbox` widgets, forcing an evaluation of the validation +command. _______________________________________________ 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]
