[Python-checkins] bpo-23216: IDLE: Add docstrings to search modules (GH-12141)

Miss Islington (bot) webhook-mailer at python.org
Sat Mar 16 19:47:32 EDT 2019


https://github.com/python/cpython/commit/b34f1aa81433d60aee7bd744352b347dd650ca84
commit: b34f1aa81433d60aee7bd744352b347dd650ca84
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2019年03月16日T16:47:28-07:00
summary:
bpo-23216: IDLE: Add docstrings to search modules (GH-12141)
(cherry picked from commit 0bb5e75cf8bc9b197ffb91cba6f30543ed502708)
Co-authored-by: Cheryl Sabella <cheryl.sabella at gmail.com>
files:
A Misc/NEWS.d/next/IDLE/2019-03-02-19-39-53.bpo-23216.ZA7H8H.rst
M Lib/idlelib/grep.py
M Lib/idlelib/replace.py
M Lib/idlelib/search.py
diff --git a/Lib/idlelib/grep.py b/Lib/idlelib/grep.py
index 873233ec1543..6068d7e4dfce 100644
--- a/Lib/idlelib/grep.py
+++ b/Lib/idlelib/grep.py
@@ -14,11 +14,16 @@
 from idlelib import searchengine
 
 # Importing OutputWindow here fails due to import loop
-# EditorWindow -> GrepDialop -> OutputWindow -> EditorWindow
+# EditorWindow -> GrepDialog -> OutputWindow -> EditorWindow
 
 
 def grep(text, io=None, flist=None):
- """Create or find singleton GrepDialog instance.
+ """Open the Find in Files dialog.
+
+ Module-level function to access the singleton GrepDialog
+ instance and open the dialog. If text is selected, it is
+ used as the search phrase; otherwise, the previous entry
+ is used.
 
 Args:
 text: Text widget that contains the selected text for
@@ -26,7 +31,6 @@ def grep(text, io=None, flist=None):
 io: iomenu.IOBinding instance with default path to search.
 flist: filelist.FileList instance for OutputWindow parent.
 """
-
 root = text._root()
 engine = searchengine.get(root)
 if not hasattr(engine, "_grepdialog"):
@@ -50,17 +54,29 @@ def __init__(self, root, engine, flist):
 searchengine instance to prepare the search.
 
 Attributes:
- globvar: Value of Text Entry widget for path to search.
- recvar: Boolean value of Checkbutton widget
- for traversing through subdirectories.
+ flist: filelist.Filelist instance for OutputWindow parent.
+ globvar: String value of Entry widget for path to search.
+ globent: Entry widget for globvar. Created in
+ create_entries().
+ recvar: Boolean value of Checkbutton widget for
+ traversing through subdirectories.
 """
- SearchDialogBase.__init__(self, root, engine)
+ super().__init__(root, engine)
 self.flist = flist
 self.globvar = StringVar(root)
 self.recvar = BooleanVar(root)
 
 def open(self, text, searchphrase, io=None):
- "Make dialog visible on top of others and ready to use."
+ """Make dialog visible on top of others and ready to use.
+
+ Extend the SearchDialogBase open() to set the initial value
+ for globvar.
+
+ Args:
+ text: Multicall object containing the text information.
+ searchphrase: String phrase to search.
+ io: iomenu.IOBinding instance containing file path.
+ """
 SearchDialogBase.open(self, text, searchphrase)
 if io:
 path = io.filename or ""
@@ -85,9 +101,9 @@ def create_other_buttons(self):
 btn.pack(side="top", fill="both")
 
 def create_command_buttons(self):
- "Create base command buttons and add button for search."
+ "Create base command buttons and add button for Search Files."
 SearchDialogBase.create_command_buttons(self)
- self.make_button("Search Files", self.default_command, 1)
+ self.make_button("Search Files", self.default_command, isdef=True)
 
 def default_command(self, event=None):
 """Grep for search pattern in file path. The default command is bound
@@ -119,6 +135,10 @@ def grep_it(self, prog, path):
 search each line for the matching pattern. If the pattern is
 found, write the file and line information to stdout (which
 is an OutputWindow).
+
+ Args:
+ prog: The compiled, cooked search pattern.
+ path: String containing the search path.
 """
 dir, base = os.path.split(path)
 list = self.findfiles(dir, base, self.recvar.get())
@@ -149,7 +169,13 @@ def grep_it(self, prog, path):
 def findfiles(self, dir, base, rec):
 """Return list of files in the dir that match the base pattern.
 
+ Use the current directory if dir has no value.
 If rec is True, recursively iterate through subdirectories.
+
+ Args:
+ dir: Directory path to search.
+ base: File search pattern.
+ rec: Boolean for recursive search through subdirectories.
 """
 try:
 names = os.listdir(dir or os.curdir)
diff --git a/Lib/idlelib/replace.py b/Lib/idlelib/replace.py
index 4a834eb7901e..6be034af9626 100644
--- a/Lib/idlelib/replace.py
+++ b/Lib/idlelib/replace.py
@@ -1,7 +1,7 @@
 """Replace dialog for IDLE. Inherits SearchDialogBase for GUI.
-Uses idlelib.SearchEngine for search capability.
+Uses idlelib.searchengine.SearchEngine for search capability.
 Defines various replace related functions like replace, replace all,
-replace+find.
+and replace+find.
 """
 import re
 
@@ -10,9 +10,16 @@
 from idlelib.searchbase import SearchDialogBase
 from idlelib import searchengine
 
+
 def replace(text):
- """Returns a singleton ReplaceDialog instance.The single dialog
- saves user entries and preferences across instances."""
+ """Create or reuse a singleton ReplaceDialog instance.
+
+ The singleton dialog saves user entries and preferences
+ across instances.
+
+ Args:
+ text: Text widget containing the text to be searched.
+ """
 root = text._root()
 engine = searchengine.get(root)
 if not hasattr(engine, "_replacedialog"):
@@ -22,16 +29,36 @@ def replace(text):
 
 
 class ReplaceDialog(SearchDialogBase):
+ "Dialog for finding and replacing a pattern in text."
 
 title = "Replace Dialog"
 icon = "Replace"
 
 def __init__(self, root, engine):
- SearchDialogBase.__init__(self, root, engine)
+ """Create search dialog for finding and replacing text.
+
+ Uses SearchDialogBase as the basis for the GUI and a
+ searchengine instance to prepare the search.
+
+ Attributes:
+ replvar: StringVar containing 'Replace with:' value.
+ replent: Entry widget for replvar. Created in
+ create_entries().
+ ok: Boolean used in searchengine.search_text to indicate
+ whether the search includes the selection.
+ """
+ super().__init__(root, engine)
 self.replvar = StringVar(root)
 
 def open(self, text):
- """Display the replace dialog"""
+ """Make dialog visible on top of others and ready to use.
+
+ Also, highlight the currently selected text and set the
+ search to include the current selection (self.ok).
+
+ Args:
+ text: Text widget being searched.
+ """
 SearchDialogBase.open(self, text)
 try:
 first = text.index("sel.first")
@@ -44,37 +71,50 @@ def open(self, text):
 first = first or text.index("insert")
 last = last or first
 self.show_hit(first, last)
- self.ok = 1
+ self.ok = True
 
 def create_entries(self):
- """Create label and text entry widgets"""
+ "Create base and additional label and text entry widgets."
 SearchDialogBase.create_entries(self)
 self.replent = self.make_entry("Replace with:", self.replvar)[0]
 
 def create_command_buttons(self):
+ """Create base and additional command buttons.
+
+ The additional buttons are for Find, Replace,
+ Replace+Find, and Replace All.
+ """
 SearchDialogBase.create_command_buttons(self)
 self.make_button("Find", self.find_it)
 self.make_button("Replace", self.replace_it)
- self.make_button("Replace+Find", self.default_command, 1)
+ self.make_button("Replace+Find", self.default_command, isdef=True)
 self.make_button("Replace All", self.replace_all)
 
 def find_it(self, event=None):
- self.do_find(0)
+ "Handle the Find button."
+ self.do_find(False)
 
 def replace_it(self, event=None):
+ """Handle the Replace button.
+
+ If the find is successful, then perform replace.
+ """
 if self.do_find(self.ok):
 self.do_replace()
 
 def default_command(self, event=None):
- "Replace and find next."
+ """Handle the Replace+Find button as the default command.
+
+ First performs a replace and then, if the replace was
+ successful, a find next.
+ """
 if self.do_find(self.ok):
 if self.do_replace(): # Only find next match if replace succeeded.
 # A bad re can cause it to fail.
- self.do_find(0)
+ self.do_find(False)
 
 def _replace_expand(self, m, repl):
- """ Helper function for expanding a regular expression
- in the replace field, if needed. """
+ "Expand replacement text if regular expression."
 if self.engine.isre():
 try:
 new = m.expand(repl)
@@ -87,7 +127,15 @@ def _replace_expand(self, m, repl):
 return new
 
 def replace_all(self, event=None):
- """Replace all instances of patvar with replvar in text"""
+ """Handle the Replace All button.
+
+ Search text for occurrences of the Find value and replace
+ each of them. The 'wrap around' value controls the start
+ point for searching. If wrap isn't set, then the searching
+ starts at the first occurrence after the current selection;
+ if wrap is set, the replacement starts at the first line.
+ The replacement is always done top-to-bottom in the text.
+ """
 prog = self.engine.getprog()
 if not prog:
 return
@@ -104,12 +152,13 @@ def replace_all(self, event=None):
 if self.engine.iswrap():
 line = 1
 col = 0
- ok = 1
+ ok = True
 first = last = None
 # XXX ought to replace circular instead of top-to-bottom when wrapping
 text.undo_block_start()
- while 1:
- res = self.engine.search_forward(text, prog, line, col, 0, ok)
+ while True:
+ res = self.engine.search_forward(text, prog, line, col,
+ wrap=False, ok=ok)
 if not res:
 break
 line, m = res
@@ -130,13 +179,17 @@ def replace_all(self, event=None):
 if new:
 text.insert(first, new)
 col = i + len(new)
- ok = 0
+ ok = False
 text.undo_block_stop()
 if first and last:
 self.show_hit(first, last)
 self.close()
 
- def do_find(self, ok=0):
+ def do_find(self, ok=False):
+ """Search for and highlight next occurrence of pattern in text.
+
+ No text replacement is done with this option.
+ """
 if not self.engine.getprog():
 return False
 text = self.text
@@ -149,10 +202,11 @@ def do_find(self, ok=0):
 first = "%d.%d" % (line, i)
 last = "%d.%d" % (line, j)
 self.show_hit(first, last)
- self.ok = 1
+ self.ok = True
 return True
 
 def do_replace(self):
+ "Replace search pattern in text with replacement value."
 prog = self.engine.getprog()
 if not prog:
 return False
@@ -180,12 +234,20 @@ def do_replace(self):
 text.insert(first, new)
 text.undo_block_stop()
 self.show_hit(first, text.index("insert"))
- self.ok = 0
+ self.ok = False
 return True
 
 def show_hit(self, first, last):
- """Highlight text from 'first' to 'last'.
- 'first', 'last' - Text indices"""
+ """Highlight text between first and last indices.
+
+ Text is highlighted via the 'hit' tag and the marked
+ section is brought into view.
+
+ The colors from the 'hit' tag aren't currently shown
+ when the text is displayed. This is due to the 'sel'
+ tag being added first, so the colors in the 'sel'
+ config are seen instead of the colors for 'hit'.
+ """
 text = self.text
 text.mark_set("insert", first)
 text.tag_remove("sel", "1.0", "end")
@@ -199,6 +261,7 @@ def show_hit(self, first, last):
 text.update_idletasks()
 
 def close(self, event=None):
+ "Close the dialog and remove hit tags."
 SearchDialogBase.close(self, event)
 self.text.tag_remove("hit", "1.0", "end")
 
diff --git a/Lib/idlelib/search.py b/Lib/idlelib/search.py
index 6e5a0c7973c7..5bbe9d6b5dc8 100644
--- a/Lib/idlelib/search.py
+++ b/Lib/idlelib/search.py
@@ -1,10 +1,23 @@
+"""Search dialog for Find, Find Again, and Find Selection
+ functionality.
+
+ Inherits from SearchDialogBase for GUI and uses searchengine
+ to prepare search pattern.
+"""
 from tkinter import TclError
 
 from idlelib import searchengine
 from idlelib.searchbase import SearchDialogBase
 
 def _setup(text):
- "Create or find the singleton SearchDialog instance."
+ """Return the new or existing singleton SearchDialog instance.
+
+ The singleton dialog saves user entries and preferences
+ across instances.
+
+ Args:
+ text: Text widget containing the text to be searched.
+ """
 root = text._root()
 engine = searchengine.get(root)
 if not hasattr(engine, "_searchdialog"):
@@ -12,31 +25,71 @@ def _setup(text):
 return engine._searchdialog
 
 def find(text):
- "Handle the editor edit menu item and corresponding event."
+ """Open the search dialog.
+
+ Module-level function to access the singleton SearchDialog
+ instance and open the dialog. If text is selected, it is
+ used as the search phrase; otherwise, the previous entry
+ is used. No search is done with this command.
+ """
 pat = text.get("sel.first", "sel.last")
 return _setup(text).open(text, pat) # Open is inherited from SDBase.
 
 def find_again(text):
- "Handle the editor edit menu item and corresponding event."
+ """Repeat the search for the last pattern and preferences.
+
+ Module-level function to access the singleton SearchDialog
+ instance to search again using the user entries and preferences
+ from the last dialog. If there was no prior search, open the
+ search dialog; otherwise, perform the search without showing the
+ dialog.
+ """
 return _setup(text).find_again(text)
 
 def find_selection(text):
- "Handle the editor edit menu item and corresponding event."
+ """Search for the selected pattern in the text.
+
+ Module-level function to access the singleton SearchDialog
+ instance to search using the selected text. With a text
+ selection, perform the search without displaying the dialog.
+ Without a selection, use the prior entry as the search phrase
+ and don't display the dialog. If there has been no prior
+ search, open the search dialog.
+ """
 return _setup(text).find_selection(text)
 
 
 class SearchDialog(SearchDialogBase):
+ "Dialog for finding a pattern in text."
 
 def create_widgets(self):
+ "Create the base search dialog and add a button for Find Next."
 SearchDialogBase.create_widgets(self)
- self.make_button("Find Next", self.default_command, 1)
+ # TODO - why is this here and not in a create_command_buttons?
+ self.make_button("Find Next", self.default_command, isdef=True)
 
 def default_command(self, event=None):
+ "Handle the Find Next button as the default command."
 if not self.engine.getprog():
 return
 self.find_again(self.text)
 
 def find_again(self, text):
+ """Repeat the last search.
+
+ If no search was previously run, open a new search dialog. In
+ this case, no search is done.
+
+ If a seach was previously run, the search dialog won't be
+ shown and the options from the previous search (including the
+ search pattern) will be used to find the next occurrence
+ of the pattern. Next is relative based on direction.
+
+ Position the window to display the located occurrence in the
+ text.
+
+ Return True if the search was successful and False otherwise.
+ """
 if not self.engine.getpat():
 self.open(text)
 return False
@@ -66,6 +119,13 @@ def find_again(self, text):
 return False
 
 def find_selection(self, text):
+ """Search for selected text with previous dialog preferences.
+
+ Instead of using the same pattern for searching (as Find
+ Again does), this first resets the pattern to the currently
+ selected text. If the selected text isn't changed, then use
+ the prior search phrase.
+ """
 pat = text.get("sel.first", "sel.last")
 if pat:
 self.engine.setcookedpat(pat)
diff --git a/Misc/NEWS.d/next/IDLE/2019-03-02-19-39-53.bpo-23216.ZA7H8H.rst b/Misc/NEWS.d/next/IDLE/2019-03-02-19-39-53.bpo-23216.ZA7H8H.rst
new file mode 100644
index 000000000000..ec091615a190
--- /dev/null
+++ b/Misc/NEWS.d/next/IDLE/2019-03-02-19-39-53.bpo-23216.ZA7H8H.rst
@@ -0,0 +1 @@
+Add docstrings to IDLE search modules.


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /