summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2023-10-24 09:59:19 (GMT)
committerGitHub <noreply@github.com>2023-10-24 09:59:19 (GMT)
commitb8c20f90492f9ef2c4600e2739f8e871a31b93c3 (patch)
tree7e0fb6e73a73903d62a347039806fb9f1eb42919
parent81eba7645082a192c027e739b8eb99a94b4c0eec (diff)
downloadcpython-b8c20f90492f9ef2c4600e2739f8e871a31b93c3.zip
cpython-b8c20f90492f9ef2c4600e2739f8e871a31b93c3.tar.gz
cpython-b8c20f90492f9ef2c4600e2739f8e871a31b93c3.tar.bz2
gh-97928: Change the behavior of tkinter.Text.count() (GH-98484)
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.
-rw-r--r--Doc/whatsnew/3.13.rst10
-rw-r--r--Lib/idlelib/sidebar.py7
-rw-r--r--Lib/test/test_tkinter/test_text.py56
-rw-r--r--Lib/tkinter/__init__.py29
-rw-r--r--Misc/NEWS.d/next/Library/2022-10-14-21-11-10.gh-issue-97928.Pdxh1G.rst6
5 files changed, 53 insertions, 55 deletions
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 4790971..a514659 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -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
diff --git a/Lib/idlelib/sidebar.py b/Lib/idlelib/sidebar.py
index fb1084d..166c043 100644
--- a/Lib/idlelib/sidebar.py
+++ b/Lib/idlelib/sidebar.py
@@ -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."""
diff --git a/Lib/test/test_tkinter/test_text.py b/Lib/test/test_tkinter/test_text.py
index 328e425..f809c45 100644
--- a/Lib/test/test_tkinter/test_text.py
+++ b/Lib/test/test_tkinter/test_text.py
@@ -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__":
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 440e7f1..47b93d3 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -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
index 0000000..4acf396
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-10-14-21-11-10.gh-issue-97928.Pdxh1G.rst
@@ -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``.
+