Surely the Text.count() method should return (0,) in the title code snippet? Following the example of what happens when more than one option is given.
I suppose the text_count method should do so too, but it was a hack of something that did not exist when written.
Tk8.6 documentation says a list of integers is returned.
Sample code below.
importtkinterdeftext_count(widget, index1, index2, *options):
"""Hack Text count command. Return integer, or tuple if len(options) > 1. Tkinter does not provide a wrapper for the Tk Text widget count command at Python 2.7.1 widget is a Tkinter Text widget. index1 and index2 are Indicies as specified in TkCmd documentation. options must be a tuple of zero or more option values. If no options are given the Tk default option is used. If less than two options are given an integer is returned. Otherwise a tuple of integers is returned (in the order specified in TkCmd documentation). See text manual page in TkCmd documentation for valid option values and index specification. Example: chars, lines = text_count(widget, start, end, '-chars', '-lines') """returnwidget.tk.call((widget._w, 'count') +options+ (index1, index2))
text=tkinter.Text()
print(text.count("1.0", tkinter.END)) # (1,0)print(text.count("1.0", "1.0")) # Noneprint(text_count(text, "1.0", "1.0")) # 0print(text_count(text, "1.0", tkinter.END)) # 1print(text.count("1.0", tkinter.END, "chars")) # (1,)print(text.count("1.0", "1.0", "chars")) # Noneprint(text_count(text, "1.0", "1.0", "-chars")) # 0print(text_count(text, "1.0", tkinter.END, "-chars")) # 1print(text.count(tkinter.END, "1.0", "chars")) # (-1,)print(text_count(text, tkinter.END, "1.0", "-chars")) # -1print(text.count("1.0", tkinter.END, "chars", "lines")) # (1, 1)print(text.count("1.0", "1.0", "chars", "lines")) # (0, 0)print(text_count(text, "1.0", "1.0", "-chars", "-lines")) # (0, 0)print(text_count(text, "1.0", tkinter.END, "-chars", "-lines")) # (1, 1)
Options starting with '-' are silently ignored. It can lead to bugs: text.count(begin, end, '-lines')) returns the the number of "indices" rather than the number of lines. Perhaps the initial intention was to only ignore the '-' prefix, so '-lines' and 'lines' would mean the same, but it never worked. It is better to make it an error.
If wantobjects was set to 0, the method returns a string.
It tries to always return a tuple (except when the result is zero count), but it fails with the 'update' option (which is undocumented in Tkinter). It returns an integer for 'update', 'ypixels' and 'update', 'indices', but a 1-tuple for 'ypixels' and 'update'.
There were no any tests for this method, so all this was unnoticed.
Other issues could be solved in compatible way, but the originally reported issue does not have backward compatible solution. Returning (0.) instead of None would make the behavior more uniform, but it would break the code if text.count(begin, end) which just checks where there is something in the interval.
I think that the decision of returning 1-tuple for a single count (unless it is zero) was a mistake. The Tk code is different for a single count and multiple code -- a single count is returned as an integer instead of a 1-list. The difference is only disappeared if convert it to string.
It would be more convenient for users to get an integer in Python too. But it is a breaking change. Choosing between two breaking changes, returning (0,) for an empty count or returning a single count as integer, I prefer the latter.
Activity
serhiy-storchaka commented on Oct 14, 2022
There are other issues with Text.count().
There were no any tests for this method, so all this was unnoticed.
Other issues could be solved in compatible way, but the originally reported issue does not have backward compatible solution. Returning (0.) instead of None would make the behavior more uniform, but it would break the code if text.count(begin, end) which just checks where there is something in the interval.
I think that the decision of returning 1-tuple for a single count (unless it is zero) was a mistake. The Tk code is different for a single count and multiple code -- a single count is returned as an integer instead of a 1-list. The difference is only disappeared if convert it to string.
It would be more convenient for users to get an integer in Python too. But it is a breaking change. Choosing between two breaking changes, returning (0,) for an empty count or returning a single count as integer, I prefer the latter.
pythongh-97928: Add tests for tkinter.Text.count()
gh-97928: Add tests for tkinter.Text.count() (GH-98269)
pythongh-97928: Add tests for tkinter.Text.count() (pythonGH-98269)
pythongh-97928: Add tests for tkinter.Text.count() (pythonGH-98269)
pythongh-97928: Fix handling options starting with "-" in tkinter.Tex…
gh-97928: Add tests for tkinter.Text.count() (GH-98269)
gh-97928: Add tests for tkinter.Text.count() (GH-98269)
gh-97928: Fix handling options starting with "-" in tkinter.Text.coun…
pythongh-97928: Fix handling options starting with "-" in tkinter.Tex…
pythongh-97928: Fix handling options starting with "-" in tkinter.Tex…
gh-97928: Fix handling options starting with "-" in tkinter.Text.coun…
gh-97928: Fix handling options starting with "-" in tkinter.Text.coun…
2 remaining items
pythongh-97928: Change the behavior of tkinter.Text.count()
gh-97928: Change the behavior of tkinter.Text.count() (GH-98484)
terryjreedy commented on Oct 24, 2023
Thanks for the fix.
serhiy-storchaka commented on Nov 28, 2023
It was suggested to partially restore the old behavior and add an optional argument return_ints to control the returned value.
terryjreedy commented on Nov 28, 2023
I clicked and read most of that discussion.
pythongh-97928: Partially restore the behavior of tkinter.Text.count(…
pythongh-97928: Partially restore the behavior of tkinter.Text.count(…
gh-97928: Partially restore the behavior of tkinter.Text.count() by d…
pythongh-97928: Change the behavior of tkinter.Text.count() (pythonGH…
pythongh-97928: Partially restore the behavior of tkinter.Text.count(…
pythongh-97928: Change the behavior of tkinter.Text.count() (pythonGH…