mirror of
https://github.com/python/cpython
synced 2024-10-14 08:31:28 +00:00
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.
This commit is contained in:
parent
81eba76450
commit
b8c20f9049
|
@ -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
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -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 @@ def test_search(self):
|
|||
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 @@ def test_count(self):
|
|||
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__":
|
||||
|
|
|
@ -3715,25 +3715,28 @@ def compare(self, index1, op, index2):
|
|||
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
|
||||
|
|
|
@ -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``.
|
||||
|
Loading…
Reference in a new issue