]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-97928: Change the behavior of tkinter.Text.count() (GH-98484)
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 24 Oct 2023 09:59:19 +0000 (12:59 +0300)
committerGitHub <noreply@github.com>
Tue, 24 Oct 2023 09:59:19 +0000 (12:59 +0300)
It now always returns an integer if one or less counting options are specified.
Previously it could return a single count as a 1-tuple, an integer (only if
option "update" was specified) or None if no items found.
The result is now the same if wantobjects is set to 0.

Doc/whatsnew/3.13.rst
Lib/idlelib/sidebar.py
Lib/test/test_tkinter/test_text.py
Lib/tkinter/__init__.py
Misc/NEWS.d/next/Library/2022-10-14-21-11-10.gh-issue-97928.Pdxh1G.rst [new file with mode: 0644]

index 4790971c376556459873c4a5cd041b3c7a2830c9..a514659e383e4b0eeb6159b5d1c51558348f8841 100644 (file)
@@ -940,7 +940,15 @@ Porting to Python 3.13
 This section lists previously described changes and other bugfixes
 that may require changes to your code.
 
-* None yet
+Changes in the Python API
+-------------------------
+
+* :meth:`!tkinter.Text.count` now always returns an integer if one or less
+  counting options are specified.
+  Previously it could return a single count as a 1-tuple, an integer (only if
+  option ``"update"`` was specified) or ``None`` if no items found.
+  The result is now the same if ``wantobjects`` is set to ``0``.
+  (Contributed by Serhiy Storchaka in :gh:`97928`.)
 
 
 Build Changes
index fb1084dbf3f18b6a9720e13afcd7f414fa414947..166c04342907f993929624c92d7f716d5960638f 100644 (file)
@@ -25,10 +25,9 @@ def get_end_linenumber(text):
 
 def get_displaylines(text, index):
     """Display height, in lines, of a logical line in a Tk text widget."""
-    res = text.count(f"{index} linestart",
-                     f"{index} lineend",
-                     "displaylines")
-    return res[0] if res else 0
+    return text.count(f"{index} linestart",
+                      f"{index} lineend",
+                      "displaylines")
 
 def get_widget_padding(widget):
     """Get the total padding of a Tk widget, including its border."""
index 328e4256ce0711eb9937e1f21eac0e8d3dc70b93..f809c4510e3a1f3e02cc6074ea6e423678a10eed 100644 (file)
@@ -10,6 +10,7 @@ class TextTest(AbstractTkTest, unittest.TestCase):
     def setUp(self):
         super().setUp()
         self.text = tkinter.Text(self.root)
+        self.text.pack()
 
     def test_debug(self):
         text = self.text
@@ -41,8 +42,6 @@ class TextTest(AbstractTkTest, unittest.TestCase):
         self.assertEqual(text.search('test', '1.0', 'end'), '1.3')
 
     def test_count(self):
-        # XXX Some assertions do not check against the intended result,
-        # but instead check the current result to prevent regression.
         text = self.text
         text.insert('1.0',
             'Lorem ipsum dolor sit amet,\n'
@@ -53,44 +52,27 @@ class TextTest(AbstractTkTest, unittest.TestCase):
         options = ('chars', 'indices', 'lines',
                    'displaychars', 'displayindices', 'displaylines',
                    'xpixels', 'ypixels')
-        if self.wantobjects:
-            self.assertEqual(len(text.count('1.0', 'end', *options)), 8)
-        else:
-            text.count('1.0', 'end', *options)
-        self.assertEqual(text.count('1.0', 'end', 'chars', 'lines'), (124, 4)
-                         if self.wantobjects else '124 4')
-        self.assertEqual(text.count('1.3', '4.5', 'chars', 'lines'), (92, 3)
-                         if self.wantobjects else '92 3')
-        self.assertEqual(text.count('4.5', '1.3', 'chars', 'lines'), (-92, -3)
-                         if self.wantobjects else '-92 -3')
-        self.assertEqual(text.count('1.3', '1.3', 'chars', 'lines'), (0, 0)
-                         if self.wantobjects else '0 0')
-        self.assertEqual(text.count('1.0', 'end', 'lines'), (4,)
-                         if self.wantobjects else ('4',))
-        self.assertEqual(text.count('end', '1.0', 'lines'), (-4,)
-                         if self.wantobjects else ('-4',))
-        self.assertEqual(text.count('1.3', '1.5', 'lines'), None
-                         if self.wantobjects else ('0',))
-        self.assertEqual(text.count('1.3', '1.3', 'lines'), None
-                         if self.wantobjects else ('0',))
-        self.assertEqual(text.count('1.0', 'end'), (124,)  # 'indices' by default
-                         if self.wantobjects else ('124',))
+        self.assertEqual(len(text.count('1.0', 'end', *options)), 8)
+        self.assertEqual(text.count('1.0', 'end', 'chars', 'lines'), (124, 4))
+        self.assertEqual(text.count('1.3', '4.5', 'chars', 'lines'), (92, 3))
+        self.assertEqual(text.count('4.5', '1.3', 'chars', 'lines'), (-92, -3))
+        self.assertEqual(text.count('1.3', '1.3', 'chars', 'lines'), (0, 0))
+        self.assertEqual(text.count('1.0', 'end', 'lines'), 4)
+        self.assertEqual(text.count('end', '1.0', 'lines'), -4)
+        self.assertEqual(text.count('1.3', '1.5', 'lines'), 0)
+        self.assertEqual(text.count('1.3', '1.3', 'lines'), 0)
+        self.assertEqual(text.count('1.0', 'end'), 124)  # 'indices' by default
+        self.assertEqual(text.count('1.0', 'end', 'indices'), 124)
         self.assertRaises(tkinter.TclError, text.count, '1.0', 'end', 'spam')
         self.assertRaises(tkinter.TclError, text.count, '1.0', 'end', '-lines')
 
-        self.assertIsInstance(text.count('1.3', '1.5', 'ypixels'), tuple)
-        self.assertIsInstance(text.count('1.3', '1.5', 'update', 'ypixels'), int
-                              if self.wantobjects else str)
-        self.assertEqual(text.count('1.3', '1.3', 'update', 'ypixels'), None
-                         if self.wantobjects else '0')
-        self.assertEqual(text.count('1.3', '1.5', 'update', 'indices'), 2
-                         if self.wantobjects else '2')
-        self.assertEqual(text.count('1.3', '1.3', 'update', 'indices'), None
-                         if self.wantobjects else '0')
-        self.assertEqual(text.count('1.3', '1.5', 'update'), (2,)
-                         if self.wantobjects else ('2',))
-        self.assertEqual(text.count('1.3', '1.3', 'update'), None
-                         if self.wantobjects else ('0',))
+        self.assertIsInstance(text.count('1.3', '1.5', 'ypixels'), int)
+        self.assertIsInstance(text.count('1.3', '1.5', 'update', 'ypixels'), int)
+        self.assertEqual(text.count('1.3', '1.3', 'update', 'ypixels'), 0)
+        self.assertEqual(text.count('1.3', '1.5', 'update', 'indices'), 2)
+        self.assertEqual(text.count('1.3', '1.3', 'update', 'indices'), 0)
+        self.assertEqual(text.count('1.3', '1.5', 'update'), 2)
+        self.assertEqual(text.count('1.3', '1.3', 'update'), 0)
 
 
 if __name__ == "__main__":
index 440e7f100c8c474e1d98409cf3fe69d2d03f9116..47b93d31fd3ffd2000c3523d6fa1a54a35ddc2c5 100644 (file)
@@ -3715,25 +3715,28 @@ class Text(Widget, XView, YView):
         return self.tk.getboolean(self.tk.call(
             self._w, 'compare', index1, op, index2))
 
-    def count(self, index1, index2, *args): # new in Tk 8.5
+    def count(self, index1, index2, *options): # new in Tk 8.5
         """Counts the number of relevant things between the two indices.
-        If index1 is after index2, the result will be a negative number
+
+        If INDEX1 is after INDEX2, the result will be a negative number
         (and this holds for each of the possible options).
 
-        The actual items which are counted depends on the options given by
-        args. The result is a list of integers, one for the result of each
-        counting option given. Valid counting options are "chars",
+        The actual items which are counted depends on the options given.
+        The result is a tuple of integers, one for the result of each
+        counting option given, if more than one option is specified,
+        otherwise it is an integer. Valid counting options are "chars",
         "displaychars", "displayindices", "displaylines", "indices",
-        "lines", "xpixels" and "ypixels". There is an additional possible
+        "lines", "xpixels" and "ypixels". The default value, if no
+        option is specified, is "indices". There is an additional possible
         option "update", which if given then all subsequent options ensure
         that any possible out of date information is recalculated."""
-        args = ['-%s' % arg for arg in args]
-        args += [index1, index2]
-        res = self.tk.call(self._w, 'count', *args) or None
-        if res is not None and len(args) <= 3:
-            return (res, )
-        else:
-            return res
+        options = ['-%s' % arg for arg in options]
+        res = self.tk.call(self._w, 'count', *options, index1, index2)
+        if not isinstance(res, int):
+            res = self._getints(res)
+            if len(res) == 1:
+                res, = res
+        return res
 
     def debug(self, boolean=None):
         """Turn on the internal consistency checks of the B-Tree inside the text
diff --git a/Misc/NEWS.d/next/Library/2022-10-14-21-11-10.gh-issue-97928.Pdxh1G.rst b/Misc/NEWS.d/next/Library/2022-10-14-21-11-10.gh-issue-97928.Pdxh1G.rst
new file mode 100644 (file)
index 0000000..4acf396
--- /dev/null
@@ -0,0 +1,6 @@
+Change the behavior of :meth:`tkinter.Text.count`. It now always returns an
+integer if one or less counting options are specified. Previously it could
+return a single count as a 1-tuple, an integer (only if option ``"update"``
+was specified) or ``None`` if no items found. The result is now the same if
+``wantobjects`` is set to ``0``.
+