From fc4d6aa158414de3cfd637ce44e06af83af8e936 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 9 Jul 2026 15:35:58 +0300 Subject: [PATCH] gh-153422: Return bool from some tkinter query methods The winfo_exists(), winfo_ismapped() and winfo_viewable() methods of tkinter widgets and Text.edit_modified() now return a bool instead of an integer or, depending on wantobjects, a string. Co-Authored-By: Claude Opus 4.8 --- Doc/library/tkinter.rst | 10 +++++----- Doc/library/tkinter.ttk.rst | 2 +- Lib/test/test_tkinter/test_images.py | 8 ++++---- Lib/test/test_tkinter/test_misc.py | 17 +++++++++++++++-- Lib/test/test_tkinter/test_text.py | 16 ++++++++-------- Lib/test/test_ttk/test_widgets.py | 6 +++--- Lib/tkinter/__init__.py | 14 ++++++++------ Lib/tkinter/ttk.py | 6 +++--- ...26-07-09-12-35-19.gh-issue-153422.tKb0Xq.rst | 4 ++++ 9 files changed, 51 insertions(+), 32 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-07-09-12-35-19.gh-issue-153422.tKb0Xq.rst diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index ca034fcdc09b43..5ced35aadbe6d3 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -2066,7 +2066,7 @@ Base and mixin classes .. method:: winfo_exists() - Return ``1`` if the widget exists, ``0`` otherwise. + Return ``True`` if the widget exists, ``False`` otherwise. .. method:: winfo_fpixels(number) @@ -2115,7 +2115,7 @@ Base and mixin classes .. method:: winfo_ismapped() - Return ``1`` if the widget is currently mapped, ``0`` otherwise. + Return ``True`` if the widget is currently mapped, ``False`` otherwise. .. method:: winfo_manager() @@ -2246,8 +2246,8 @@ Base and mixin classes .. method:: winfo_viewable() - Return ``1`` if the widget and all of its ancestors up through the - nearest toplevel window are mapped, ``0`` otherwise. + Return ``True`` if the widget and all of its ancestors up through the + nearest toplevel window are mapped, ``False`` otherwise. .. method:: winfo_visual() @@ -5737,7 +5737,7 @@ Widget classes .. method:: edit_modified(arg=None) If *arg* is omitted, return the current state of the modified flag as - ``0`` or ``1``; the flag is set automatically whenever the text is + a :class:`bool`; the flag is set automatically whenever the text is inserted or deleted. Otherwise set the flag to the boolean *arg*. diff --git a/Doc/library/tkinter.ttk.rst b/Doc/library/tkinter.ttk.rst index 13b374e23558fc..fdffa5ebb5da45 100644 --- a/Doc/library/tkinter.ttk.rst +++ b/Doc/library/tkinter.ttk.rst @@ -1372,7 +1372,7 @@ ttk.Treeview Without arguments, returns a tuple of all detached items, but not their descendants (see :meth:`detached_all`). With *item*, returns whether *item* is detached; since Tk 9.1, also - returns true if an ancestor of *item* is detached. + returns ``True`` if an ancestor of *item* is detached. Requires Tk 9.0 or newer. diff --git a/Lib/test/test_tkinter/test_images.py b/Lib/test/test_tkinter/test_images.py index 4ce66340620333..e884f7122c8adc 100644 --- a/Lib/test/test_tkinter/test_images.py +++ b/Lib/test/test_tkinter/test_images.py @@ -694,12 +694,12 @@ def test_data(self): def test_transparency(self): image = self.create() - self.assertEqual(image.transparency_get(0, 0), True) - self.assertEqual(image.transparency_get(4, 6), False) + self.assertIs(image.transparency_get(0, 0), True) + self.assertIs(image.transparency_get(4, 6), False) image.transparency_set(4, 6, True) - self.assertEqual(image.transparency_get(4, 6), True) + self.assertIs(image.transparency_get(4, 6), True) image.transparency_set(4, 6, False) - self.assertEqual(image.transparency_get(4, 6), False) + self.assertIs(image.transparency_get(4, 6), False) self.assertRaises(tkinter.TclError, image.transparency_get, -1, 0) self.assertRaises(tkinter.TclError, image.transparency_get, 16, 0) self.assertRaises(tkinter.TclError, image.transparency_set, -1, 0, True) diff --git a/Lib/test/test_tkinter/test_misc.py b/Lib/test/test_tkinter/test_misc.py index 5f75b8d245b3e9..5a25d3689df89c 100644 --- a/Lib/test/test_tkinter/test_misc.py +++ b/Lib/test/test_tkinter/test_misc.py @@ -905,13 +905,26 @@ def test_winfo_visual_info(self): self.assertIsInstance(name, str) self.assertIsInstance(depth, int) + def test_winfo_exists(self): + f = tkinter.Frame(self.root) + self.assertIs(f.winfo_exists(), True) + f.destroy() + self.assertIs(f.winfo_exists(), False) + + def test_winfo_ismapped(self): + f = tkinter.Frame(self.root) + self.assertIs(f.winfo_ismapped(), False) + f.pack() + self.root.update() + self.assertIs(f.winfo_ismapped(), True) + def test_winfo_viewable(self): f = tkinter.Frame(self.root) - self.assertFalse(f.winfo_viewable()) + self.assertIs(f.winfo_viewable(), False) f.pack() f.wait_visibility() self.root.update() - self.assertTrue(f.winfo_viewable()) + self.assertIs(f.winfo_viewable(), True) @requires_tk(9, 1) def test_winfo_isdark(self): diff --git a/Lib/test/test_tkinter/test_text.py b/Lib/test/test_tkinter/test_text.py index 905c194af3ac47..7ff837900f8959 100644 --- a/Lib/test/test_tkinter/test_text.py +++ b/Lib/test/test_tkinter/test_text.py @@ -18,10 +18,10 @@ def test_debug(self): text = self.text olddebug = text.debug() try: - text.debug(0) - self.assertEqual(text.debug(), 0) - text.debug(1) - self.assertEqual(text.debug(), 1) + text.debug(False) + self.assertIs(text.debug(), False) + text.debug(True) + self.assertIs(text.debug(), True) finally: text.debug(olddebug) self.assertEqual(text.debug(), olddebug) @@ -293,13 +293,13 @@ def test_tag_cget_configure(self): def test_edit_modified(self): text = self.text - self.assertEqual(text.edit_modified(), 0) + self.assertIs(text.edit_modified(), False) text.insert('1.0', 'spam') - self.assertEqual(text.edit_modified(), 1) + self.assertIs(text.edit_modified(), True) text.edit_modified(False) - self.assertEqual(text.edit_modified(), 0) + self.assertIs(text.edit_modified(), False) text.edit_modified(True) - self.assertEqual(text.edit_modified(), 1) + self.assertIs(text.edit_modified(), True) def test_edit_undo_redo(self): text = self.text diff --git a/Lib/test/test_ttk/test_widgets.py b/Lib/test/test_ttk/test_widgets.py index b86d56f256e9e8..a51a0b4e61c133 100644 --- a/Lib/test/test_ttk/test_widgets.py +++ b/Lib/test/test_ttk/test_widgets.py @@ -1685,9 +1685,9 @@ def test_detach_reattach(self): self.assertEqual(self.tv.get_children(item_id), ()) def test_exists(self): - self.assertEqual(self.tv.exists('something'), False) - self.assertEqual(self.tv.exists(''), True) - self.assertEqual(self.tv.exists({}), False) + self.assertIs(self.tv.exists('something'), False) + self.assertIs(self.tv.exists(''), True) + self.assertIs(self.tv.exists({}), False) # the following will make a tk.call equivalent to # tk.call(treeview, "exists") which should result in an error diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index 83d11a7695ffbe..b37a504ae9ff21 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -1332,8 +1332,8 @@ def winfo_depth(self): return self.tk.getint(self.tk.call('winfo', 'depth', self._w)) def winfo_exists(self): - """Return true if this widget exists.""" - return self.tk.getint( + """Return True if this widget exists.""" + return self.tk.getboolean( self.tk.call('winfo', 'exists', self._w)) def winfo_fpixels(self, number): @@ -1370,8 +1370,8 @@ def winfo_isdark(self): # new in Tk 9.1 self.tk.call('winfo', 'isdark', self._w)) def winfo_ismapped(self): - """Return true if this widget is mapped.""" - return self.tk.getint( + """Return True if this widget is mapped.""" + return self.tk.getboolean( self.tk.call('winfo', 'ismapped', self._w)) def winfo_manager(self): @@ -1498,8 +1498,8 @@ def winfo_toplevel(self): 'winfo', 'toplevel', self._w)) def winfo_viewable(self): - """Return true if the widget and all its higher ancestors are mapped.""" - return self.tk.getint( + """Return True if the widget and all its higher ancestors are mapped.""" + return self.tk.getboolean( self.tk.call('winfo', 'viewable', self._w)) def winfo_visual(self): @@ -4207,6 +4207,8 @@ def edit_modified(self, arg=None): modified flag. If boolean is specified, sets the modified flag of the widget to arg. """ + if arg is None: + return self.tk.getboolean(self.edit("modified")) return self.edit("modified", arg) def edit_redo(self): diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py index 69ac31c9e1244d..57953d90b672a2 100644 --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -1604,7 +1604,7 @@ def detached(self, item=None): Without arguments, return a tuple of all detached items (but not their descendants; see detached_all). With item, return whether item - is detached; since Tk 9.1, also return true if an ancestor of item + is detached; since Tk 9.1, also return True if an ancestor of item is detached. * Availability: Tk 9.0""" @@ -2031,8 +2031,8 @@ def tag_configure(self, tagname, option=None, **kw): def tag_has(self, tagname, item=None): - """If item is specified, returns 1 or 0 depending on whether the - specified item has the given tagname. Otherwise, returns a list of + """If item is specified, returns True if the specified item has the + given tagname, False otherwise. Otherwise, returns a list of all items which have the specified tag. * Availability: Tk 8.6""" diff --git a/Misc/NEWS.d/next/Library/2026-07-09-12-35-19.gh-issue-153422.tKb0Xq.rst b/Misc/NEWS.d/next/Library/2026-07-09-12-35-19.gh-issue-153422.tKb0Xq.rst new file mode 100644 index 00000000000000..16bd5c9a22fbde --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-09-12-35-19.gh-issue-153422.tKb0Xq.rst @@ -0,0 +1,4 @@ +:meth:`!winfo_exists`, :meth:`!winfo_ismapped` and :meth:`!winfo_viewable` +methods of :mod:`tkinter` widgets and :meth:`!edit_modified` of +:class:`tkinter.Text` now return a :class:`bool` instead of an integer or, +depending on ``wantobjects``, a string.