10000 bpo-23216: IDLE: Add docstrings to search modules (GH-12141) · python/cpython@0bb5e75 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0bb5e75

Browse files
authored
bpo-23216: IDLE: Add docstrings to search modules (GH-12141)
1 parent 7c99454 commit 0bb5e75

File tree

4 files changed

+189
-39
lines changed

4 files changed

+189
-39
lines changed

Lib/idlelib/grep.py

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,23 @@
1414
from idlelib import searchengine
1515

1616
# Importing OutputWindow here fails due to import loop
17-
# EditorWindow -> GrepDialop -> OutputWindow -> EditorWindow
17+
# EditorWindow -> GrepDialog -> OutputWindow -> EditorWindow
1818

1919

2020
def grep(text, io=None, flist=None):
21-
"""Create or find singleton GrepDialog instance.
21+
"""Open the Find in Files dialog.
22+
23+
Module-level function to access the singleton GrepDialog
24+
instance and open the dialog. If text is selected, it is
25+
used as the search phrase; otherwise, the previous entry
26+
is used.
2227
2328
Args:
2429
text: Text widget that contains the selected text for
2530
default search phrase.
2631
io: iomenu.IOBinding instance with default path to search.
2732
flist: filelist.FileList instance for OutputWindow parent.
2833
"""
29-
3034
root = text._root()
3135
engine = searchengine.get(root)
3236
if not hasattr(engine, "_grepdialog"):
@@ -50,17 +54,29 @@ def __init__(self, root, engine, flist):
5054
searchengine instance to prepare the search.
5155
5256
Attributes:
53-
globvar: Value of Text Entry widget for path to search.
54-
recvar: Boolean value of Checkbutton widget
55-
for traversing through subdirectories.
57+
flist: filelist.Filelist instance for OutputWindow parent.
58+
globvar: String value of Entry widget for path to search.
59+
globent: Entry widget for globvar. Created in
60+
create_entries().
61+
recvar: Boolean value of Checkbutton widget for
62+
traversing through subdirectories.
5663
"""
57-
SearchDialogBase.__init__(self, root, engine)
64+
super().__init__(root, engine)
5865
self.flist = flist
5966
self.globvar = StringVar(root)
6067
self.recvar = BooleanVar(root)
6168

6269
def open(self, text, searchphrase, io=None):
63-
"Make dialog visible on top of others and ready to use."
70+
"""Make dialog visible on top of others and ready to use.
71+
72+
Extend the SearchDialogBase open() to set the initial value
73+
for globvar.
74+
75+
Args:
76+
text: Multicall object containing the text information.
77+
searchphrase: String phrase to search.
78+
io: iomenu.IOBinding instance containing file path.
79+
"""
6480
SearchDialogBase.open(self, text, searchphrase)
6581
if io:
6682
path = io.filename or ""
@@ -85,9 +101,9 @@ def create_other_buttons(self):
85101
btn.pack(side="top", fill="both")
86102

87103
def create_command_buttons(self):
88-
"Create base command buttons and add button for search."
104+
"Create base command buttons and add button for Search Files."
89105
SearchDialogBase.create_command_buttons(self)
90-
self.make_button("Search Files", self.default_command, 1)
106+
self.make_button("Search Files", self.default_command, isdef=True)
91107

92108
def default_command(self, event=None):
93109
"""Grep for search pattern in file path. The default command is bound
@@ -119,6 +135,10 @@ def grep_it(self, prog, path):
119135
search each line for the matching pattern. If the pattern is
120136
found, write the file and line information to stdout (which
121137
is an OutputWindow).
138+
139+
Args:
140+
prog: The compiled, cooked search pattern.
141+
path: String containing the search path.
122142
"""
123143
dir, base = os.path.split(path)
124144
list = self.findfiles(dir, base, self.recvar.get())
@@ -149,7 +169,13 @@ def grep_it(self, prog, path):
149169
def findfiles(self, dir, base, rec):
150170
"""Return list of files in the dir that match the base pattern.
151171
172+
Use the current directory if dir has no value.
152173
If rec is True, recursively iterate through subdirectories.
174+
175+
Args:
176+
dir: Directory path to search.
177+
base: File search pattern.
178+
rec: Boolean for recursive search through subdirectories.
153179
"""
154180
try:
155181
names = os.listdir(dir or os.curdir)

Lib/idlelib/replace.py

Lines changed: 87 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Replace dialog for IDLE. Inherits SearchDialogBase for GUI.
2-
Uses idlelib.SearchEngine for search capability.
2+
Uses idlelib.searchengine.SearchEngine for search capability.
33
Defines various replace related functions like replace, replace all,
4-
replace+find.
4+
and replace+find.
55
"""
66
import re
77

@@ -10,9 +10,16 @@
1010
from idlelib.searchbase import SearchDialogBase
1111
from idlelib import searchengine
1212

13+
1314
def replace(text):
14-
"""Returns a singleton ReplaceDialog instance.The single dialog
15-
saves user entries and preferences across instances."""
15+
"""Create or reuse a singleton ReplaceDialog instance.
16+
17+
The singleton dialog saves user entries and preferences
18+
across instances.
19+
20+
Args:
21+
text: Text widget containing the text to be searched.
22+
"""
1623
root = text._root()
1724
engine = searchengine.get(root)
1825
if not hasattr(engine, "_replacedialog"):
@@ -22,16 +29,36 @@ def replace(text):
2229

2330

2431
class ReplaceDialog(SearchDialogBase):
32+
"Dialog for finding and replacing a pattern in text."
2533

2634
title = "Replace Dialog"
2735
icon = "Replace"
2836

2937
def __init__(self, root, engine):
30-
SearchDialogBase.__init__(self, root, engine)
38+
"""Create search dialog for finding and replacing text.
39+
40+
Uses SearchDialogBase as the basis for the GUI and a
41+
searchengine instance to prepare the search.
42+
43+
Attributes:
44+
replvar: StringVar containing 'Replace with:' value.
45+
replent: Entry widget for replvar. Created in
46+
create_entries().
47+
ok: Boolean used in searchengine.search_text to indicate
48+
whether the search includes the selection.
49+
"""
50+
super().__init__(root, engine)
3151
self.replvar = StringVar(root)
3252

3353
def open(self, text):
34-
"""Display the replace dialog"""
54+
"""Make dialog visible on top of others and ready to use.
55+
56+
Also, highlight the currently selected text and set the
57+
search to include the current selection (self.ok).
58+
59+
Args:
60+
text: Text widget being searched.
61+
"""
3562
SearchDialogBase.open(self, text)
3663
try:
3764
first = text.index("sel.first")
@@ -44,37 +71,50 @@ def open(self, text):
4471
first = first or text.index("insert")
4572
last = last or first
4673
self.show_hit(first, last)
47-
self.ok = 1
74+
self.ok = True
4875

4976
def create_entries(self):
50-
"""Create label and text entry widgets"""
77+
"Create base and additional label and text entry widgets."
5178
SearchDialogBase.create_entries(self)
5279
self.replent = self.make_entry("Replace with:", self.replvar)[0]
5380

5481
def create_command_buttons(self):
82+
"""Create base and additional command buttons.
83+
84+
The additional buttons are for Find, Replace,
85+
Replace+Find, and Replace All.
86+
"""
5587
SearchDialogBase.create_command_buttons(self)
5688
self.make_button("Find", self.find_it)
5789
self.make_button("Replace", self.replace_it)
58-
self.make_button("Replace+Find", self.default_command, 1)
90+
self.make_button("Replace+Find", self.default_command, isdef=True)
5991
self.make_button("Replace All", self.replace_all)
6092

6193
def find_it(self, event=None):
62-
self.do_find(0)
94+
"Handle the Find button."
95+
self.do_find(False)
6396

6497
def replace_it(self, event=None):
98+
"""Handle the Replace button.
99+
100+
If the find is successful, then perform replace.
101+
"""
65102
if self.do_find(self.ok):
66103
self.do_replace()
67104

68105
def default_command(self, event=None):
69-
"Replace and find next."
106+
"""Handle the Replace+Find button as the default command.
107+
108+
First performs a replace and then, if the replace was
109+
successful, a find next.
110+
"""
70111
if self.do_find(self.ok):
71112
if self.do_replace(): # Only find next match if replace succeeded.
72113
# A bad re can cause it to fail.
73-
self.do_find(0)
114+
self.do_find(False)
74115

75116
def _replace_expand(self, m, repl):
76-
""" Helper function for expanding a regular expression
77-
in the replace field, if needed. """
117+
"Expand replacement text if regular expression."
78118
if self.engine.isre():
79119
try:
80120
new = m.expand(repl)
@@ -87,7 +127,15 @@ def _replace_expand(self, m, repl):
87127
return new
88128

89129
def replace_all(self, event=None):
90-
"""Replace all instances of patvar with replvar in text"""
130+
"""Handle the Replace All button.
131+
132+
Search text for occurrences of the Find value and replace
133+
each of them. The 'wrap around' value controls the start
134+
point for searching. If wrap isn't set, then the searching
135+
starts at the first occurrence after the current selection;
136+
if wrap is set, the replacement starts at the first line.
137+
The replacement is always done top-to-bottom in the text.
138+
"""
91139
prog = self.engine.getprog()
92140
if not prog:
93141
return
@@ -104,12 +152,13 @@ def replace_all(self, event=None):
104152
if self.engine.iswrap():
105153
line = 1
106154
col = 0
107-
ok = 1
155+
ok = True
108156
first = last = None
109157
# XXX ought to replace circular instead of top-to-bottom when wrapping
110158
text.undo_block_start()
111-
while 1:
112-
res = self.engine.search_forward(text, prog, line, col, 0, ok)
159+
while True:
160+
res = self.engine.search_forward(text, prog, line, col,
161+
wrap=False, ok=ok)
113162
if not res:
114163
break
115164
line, m = res
@@ -130,13 +179,17 @@ def replace_all(self, event=None):
130179
if new:
131180
text.insert(first, new)
132181
col = i + len(new)
133-
ok = 0
182+
ok = False
134183
text.undo_block_stop()
135184
if first and last:
136185
self.show_hit(first, last)
137186
self.close()
138187

139-
def do_find(self, ok=0):
188+
def do_find(self, ok=False):
189+
"""Search for and highlight next occurrence of pattern in text.
190+
191+
No text replacement is done with this option.
192+
"""
140193
if not self.engine.getprog():
141194
return False
142195
text = self.text
@@ -149,10 +202,11 @@ def do_find(self, ok=0):
149202
first = "%d.%d" % (line, i)
150203
last = "%d.%d" % (line, j)
151204
self.show_hit(first, last)
152-
self.ok = 1
205+
self.ok = True
153206
return True
154207

155208
def do_replace(self):
209+
"Replace search pattern in text with replacement value."
156210
prog = self.engine.getprog()
157211
if not prog:
158212
return False
@@ -180,12 +234,20 @@ def do_replace(self):
180234
text.insert(first, new)
181235
text.undo_block_stop()
182236
self.show_hit(first, text.index("insert"))
183-
self.ok = 0
237+
self.ok = False
184238
return True
185239

186240
def show_hit(self, first, last):
187-
"""Highlight text from 'first' to 'last'.
188-
'first', 'last' - Text indices"""
241+
"""Highlight text between first and last indices.
242+
243+
Text is highlighted via the 'hit' tag and the marked
244+
section is brought into view.
245+
246+
The colors from the 'hit' tag aren't currently shown
247+
when the text is displayed. This is due to the 'sel'
248+
tag being added first, so the colors in the 'sel'
249+
config are seen instead of the colors for 'hit'.
250+
"""
189251
text = self.text
190252
text.mark_set("insert", first)
191253
text.tag_remove("sel", "1.0", "end")
@@ -199,6 +261,7 @@ def show_hit(self, first, last):
199261
text.update_idletasks()
200262

201263
def close(self, event=None):
264+
"Close the dialog and remove hit tags."
202265
SearchDialogBase.close(self, event)
203266
self.text.tag_remove("hit", "1.0", "end")
204267

0 commit comments

Comments
 (0)
0