]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-151878: Add tkinter Entry and Spinbox validate methods (GH-151879)
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 22 Jun 2026 12:52:50 +0000 (15:52 +0300)
committerGitHub <noreply@github.com>
Mon, 22 Jun 2026 12:52:50 +0000 (12:52 +0000)
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 <noreply@anthropic.com>
Doc/library/tkinter.rst
Doc/whatsnew/3.16.rst
Lib/test/test_tkinter/test_widgets.py
Lib/tkinter/__init__.py
Misc/NEWS.d/next/Library/2026-06-22-01-02-33.gh-issue-151878.IFIA5C.rst [new file with mode: 0644]

index 249b1602a711addde814f74e142d34fe5d1a1283..13fe3514b5ebc8caa8e0ba6818e3689de07ba65f 100644 (file)
@@ -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)
index 8abc4d0af8d19fc8a9f03474b3ff66a0587ef3c2..3c625801c46a1cda1f6b6413e9e8bfffeae42be9 100644 (file)
@@ -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).
index 4b51d219d87e5be9d0d659efc535986f4e039ee9..d0305562a0cb05bfcc7bb66eb7c180886685aa18 100644 (file)
@@ -589,6 +589,25 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
         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):
index 68de4a35689691f6a7adb2a61989c4461c053721..974e386be1bb492d56e59237dfb670e4b5827931 100644 (file)
@@ -3445,6 +3445,14 @@ class Entry(Widget, XView):
 
     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 @@ class Spinbox(Widget, XView):
         """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 (file)
index 0000000..af0d2c2
--- /dev/null
@@ -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.