Skip to content

gh-130693: Add options of the tkinter.Text.search method: -nolinestop -all -overlap -strictlimits #130848

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 43 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
8b27bcb
Update __init__.py
sharktide Mar 4, 2025
18d5005
📜🤖 Added by blurb_it.
blurb-it[bot] Mar 4, 2025
e2a76c2
Update 2025-03-04-17-19-26.gh-issue-130693.Kv01r8.rst
sharktide Mar 4, 2025
753da3a
Update 2025-03-04-17-19-26.gh-issue-130693.Kv01r8.rst
sharktide Mar 5, 2025
1ca30c6
Update 2025-03-04-17-19-26.gh-issue-130693.Kv01r8.rst
sharktide Mar 5, 2025
548e36a
Merge branch 'python:main' into patch-130693
sharktide May 5, 2025
6ce83e3
pythongh-130693 Remove wordiness; only title left
sharktide May 5, 2025
39f5875
Update 2025-03-04-17-19-26.gh-issue-130693.Kv01r8.rst
sharktide May 30, 2025
ba0c98a
remove whitespace in Lib/tkinter/__init__.py
sharktide Jun 17, 2025
754a124
Revert formatting in Lib/tkinter/__init__.py
sharktide Jun 17, 2025
ffd95fa
Update news entry to use :meth: tags
sharktide Jun 17, 2025
72e70fc
Merge branch 'main' into patch-130693
sharktide Jun 17, 2025
6229bdf
Remove newlines in news entry
sharktide Jun 17, 2025
1843da6
Remove ref to nonexistent docs (needs to be fixed later)
sharktide Jun 17, 2025
7196a88
Use double backticks in news entry
sharktide Jun 17, 2025
2601ddf
Add test cases to test_text.py
sharktide Jun 18, 2025
6d18d2f
Fix test failures due to return type being tcl obj not tuple
sharktide Jun 18, 2025
b672353
Make linter happy
sharktide Jun 18, 2025
bb9a840
Fix test fails by making 1.10 assumption broader
sharktide Jun 18, 2025
cc80963
Try to fix test fails again
sharktide Jun 18, 2025
8c8409c
Update __init__.py
sharktide Jul 27, 2025
980a5e3
Merge options tests into test_search
sharktide Aug 10, 2025
fb30d25
Remove -all and -overlap from search() and create search_all()
sharktide Aug 10, 2025
d58a291
Explicitly return list and convert tcl objects into strings
sharktide Aug 10, 2025
d3621e2
Modify test_search to also test search_all()
sharktide Aug 10, 2025
dfe46c0
Add to whatsnew.rst
sharktide Aug 10, 2025
efc1685
Merge branch 'main' into patch-130693
sharktide Aug 10, 2025
a286199
Fix text fauilures
sharktide Aug 10, 2025
9cf844a
Update news entry
sharktide Aug 10, 2025
834d6d4
Update whatsnew again
sharktide Aug 10, 2025
e4c7bef
Fix fails, reword
sharktide Aug 10, 2025
7cb79b9
Fix lint fails, add heading in what’s new
sharktide Aug 11, 2025
026ded8
Remove breaking changes
sharktide Aug 11, 2025
430773c
Use self.tk._splitlist
sharktide Aug 11, 2025
2f5ad84
Use ASCII dashes and move to improved modules
sharktide Aug 11, 2025
71d2a60
Revert docstring and make search_all keyword only
sharktide Aug 11, 2025
77831d4
Allow for other return types in list
sharktide Aug 11, 2025
1daff0f
Value based assertions
sharktide Aug 11, 2025
422aa6f
Remove - where not necessary, add newlines
sharktide Aug 11, 2025
1328308
Fix test fails
sharktide Aug 11, 2025
6e3d0c9
Update type expectations from list to tuple
sharktide Aug 11, 2025
6c6520b
Update assertion values
sharktide Aug 11, 2025
2852ee2
Use suggestions
sharktide Aug 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ production systems where traditional profiling approaches would be too intrusive

(Contributed by Pablo Galindo and László Kiss Kollár in :gh:`135953`.)


Other language changes
======================

Expand Down Expand Up @@ -354,6 +353,19 @@ tarfile
(Contributed by Matt Prodani and Petr Viktorin in :gh:`112887`
and :cve:`2025-4435`.)

tkinter
-------

* The :meth:`!tkinter.Text.search` method now supports two additional
arguments: *nolinestop* which allows the search to
continue across line boundaries;
and *strictlimits* which restricts the search to within the specified range.
(Contributed by Rihaan Meher in :gh:`130848`)

* A new method :meth:`!tkinter.Text.search_all` has been introduced.
This method allows for searching for all matches of a pattern
using Tcl's ``-all`` and ``-overlap`` options.
(Contributed by Rihaan Meher in :gh:`130848`)

types
------
Expand Down
42 changes: 41 additions & 1 deletion Lib/test/test_tkinter/test_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,47 @@ def test_search(self):
self.assertEqual(text.search('-test', '1.0', 'end'), '1.2')
self.assertEqual(text.search('test', '1.0', 'end'), '1.3')

text.delete('1.0', 'end')
text.insert('1.0',
'This is a test. This is only a test.\n'
'Another line.\n'
'Yet another line.')

result = text.search('line', '1.0', 'end', nolinestop=True, regexp=True)
self.assertEqual(result, '2.8')

strict_res = text.search('test', '1.0', '1.20', strictlimits=True)
self.assertEqual(strict_res, '1.10')

def test_search_all(self):
text = self.text
text.insert('1.0',
'ababa ababa\n'
'ababababa\n'
'aba aba')

all_res = text.search_all('aba', '1.0', 'end')
all_res_strs = [str(i) for i in all_res]
self.assertIsInstance(all_res, tuple)
self.assertGreaterEqual(len(all_res), 3)
self.assertEqual(str(all_res[0]), '1.0')
self.assertEqual(str(all_res[1]), '1.6')

overlap_res = text.search_all('aba', '1.0', 'end', overlap=True)
overlap_res_strs = [str(i) for i in overlap_res]
self.assertIsInstance(overlap_res, tuple)
self.assertGreater(len(overlap_res), len(all_res))

# Check that overlap actually finds overlapping matches
self.assertIn('2.0', overlap_res_strs)
self.assertIn('2.2', overlap_res_strs)
self.assertIn('2.4', overlap_res_strs)
self.assertNotIn('2.2', all_res_strs)

# Ensure all results are valid text indices
for i in overlap_res:
self.assertRegex(str(i), r'^\d+\.\d+$')

def test_count(self):
text = self.text
text.insert('1.0',
Expand Down Expand Up @@ -94,6 +135,5 @@ def test_count(self):
self.assertEqual(text.count('1.3', '1.3', 'update', return_ints=True), 0)
self.assertEqual(text.count('1.3', '1.3', 'update'), None)


if __name__ == "__main__":
unittest.main()
32 changes: 30 additions & 2 deletions Lib/tkinter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4039,8 +4039,9 @@ def scan_dragto(self, x, y):
self.tk.call(self._w, 'scan', 'dragto', x, y)

def search(self, pattern, index, stopindex=None,
forwards=None, backwards=None, exact=None,
regexp=None, nocase=None, count=None, elide=None):
forwards=None, backwards=None, exact=None,
regexp=None, nocase=None, count=None,
elide=None, nolinestop=None, strictlimits=None):
"""Search PATTERN beginning from INDEX until STOPINDEX.
Return the index of the first character of a match or an
empty string."""
Expand All @@ -4052,12 +4053,39 @@ def search(self, pattern, index, stopindex=None,
if nocase: args.append('-nocase')
if elide: args.append('-elide')
if count: args.append('-count'); args.append(count)
if nolinestop: args.append('-nolinestop')
if strictlimits: args.append('-strictlimits')
if pattern and pattern[0] == '-': args.append('--')
args.append(pattern)
args.append(index)
if stopindex: args.append(stopindex)
return str(self.tk.call(tuple(args)))

def search_all(self, pattern, index, stopindex=None, *,
forwards=None, backwards=None, exact=None,
regexp=None, nocase=None, count=None,
elide=None, nolinestop=None, overlap=None,
strictlimits=None):
"""Search all occurrences of PATTERN from INDEX to STOPINDEX.
Return a tuple of indices where matches begin."""
args = [self._w, 'search', '-all']
if forwards: args.append('-forwards')
if backwards: args.append('-backwards')
if exact: args.append('-exact')
if regexp: args.append('-regexp')
if nocase: args.append('-nocase')
if elide: args.append('-elide')
if count: args.append('-count'); args.append(count)
if nolinestop: args.append('-nolinestop')
if overlap: args.append('-overlap')
if strictlimits: args.append('-strictlimits')
if pattern and pattern[0] == '-': args.append('--')
args.append(pattern)
args.append(index)
if stopindex: args.append(stopindex)
result = self.tk.call(tuple(args))
return self.tk.splitlist(result)

def see(self, index):
"""Scroll such that the character at INDEX is visible."""
self.tk.call(self._w, 'see', index)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for ``-nolinestop``, and ``-strictlimits`` options to :meth:`!tkinter.Text.search`. Also add the :meth:`!tkinter.Text.search_all` method for ``-all`` and ``-overlap`` options.
Loading