diff -r 2adb8af9fffd Lib/idlelib/README.txt --- a/Lib/idlelib/README.txt Mon Jun 27 12:31:00 2016 -0700 +++ b/Lib/idlelib/README.txt Mon Jun 27 22:26:27 2016 -0400 @@ -41,7 +41,6 @@ configdialog.py # Display user configuration dialogs. config_help.py # Specify help source in configdialog. config_key.py # Change keybindings. -config_sec.py # Spefify user config section name dynoption.py # Define mutable OptionMenu widget (nim). debugobj.py # Define class used in stackviewer. debugobj_r.py # Communicate objects between processes with rpc (nim). @@ -66,6 +65,7 @@ percolator.py # Manage delegator stack (nim). pyparse.py # Give information on code indentation pyshell.py # Start IDLE, manage shell, complete editor window +query.py # Query user for informtion redirector.py # Intercept widget subcommands (for percolator) (nim). replace.py # Search and replace pattern in text. rpc.py # Commuicate between idle and user processes (nim). @@ -192,8 +192,8 @@ Configure IDLE # eEW.config_dialog, configdialog (tabs in the dialog) Font tab # config-main.def - Highlight tab # config_sec, config-highlight.def - Keys tab # config_key, configconfig_secg-keus.def + Highlight tab # query, config-highlight.def + Keys tab # query, config_key, config_keys.def General tab # config_help, config-main.def Extensions tab # config-extensions.def, corresponding .py --- diff -r 2adb8af9fffd Lib/idlelib/editor.py --- a/Lib/idlelib/editor.py Mon Jun 27 12:31:00 2016 -0700 +++ b/Lib/idlelib/editor.py Mon Jun 27 22:26:27 2016 -0400 @@ -14,6 +14,7 @@ import webbrowser from idlelib.multicall import MultiCallCreator +from idlelib import query from idlelib import windows from idlelib import search from idlelib import grep @@ -573,46 +574,27 @@ text.see("insert") def open_module(self, event=None): - # XXX Shouldn't this be in IOBinding? + """Get module name from user and open it. + + Return module path or None for calls by open_class_browser + when latter is not invoked in named editor window. + """ + # XXX This, open_class_browser, and open_path_browser + # would fit better in iomenu.IOBinding. try: - name = self.text.get("sel.first", "sel.last") + name = self.text.get("sel.first", "sel.last").strip() except TclError: name = "" - else: - name = name.strip() - name = tkSimpleDialog.askstring("Module", - "Enter the name of a Python module\n" - "to search on sys.path and open:", - parent=self.text, initialvalue=name) - if name: - name = name.strip() - if not name: - return - # XXX Ought to insert current file's directory in front of path - try: - spec = importlib.util.find_spec(name) - except (ValueError, ImportError) as msg: - tkMessageBox.showerror("Import error", str(msg), parent=self.text) - return - if spec is None: - tkMessageBox.showerror("Import error", "module not found", - parent=self.text) - return - if not isinstance(spec.loader, importlib.abc.SourceLoader): - tkMessageBox.showerror("Import error", "not a source-based module", - parent=self.text) - return - try: - file_path = spec.loader.get_filename(name) - except AttributeError: - tkMessageBox.showerror("Import error", - "loader does not support get_filename", - parent=self.text) - return - if self.flist: - self.flist.open(file_path) - else: - self.io.loadfile(file_path) + file_path = query.ModuleName( + self.text, "Open Module", + "Enter the name of a Python module\n" + "to search on sys.path and open:", + name).result + if file_path is not None: + if self.flist: + self.flist.open(file_path) + else: + self.io.loadfile(file_path) return file_path def open_class_browser(self, event=None): diff -r 2adb8af9fffd Lib/idlelib/idle_test/htest.py --- a/Lib/idlelib/idle_test/htest.py Mon Jun 27 12:31:00 2016 -0700 +++ b/Lib/idlelib/idle_test/htest.py Mon Jun 27 22:26:27 2016 -0400 @@ -235,8 +235,9 @@ Query_spec = { 'file': 'query', - 'kwds': {'title':'Query', - 'message':'Enter something', + 'kwds': {'title': 'Query', + 'message': 'Enter something', + 'text0': 'Go', '_htest': True}, 'msg': "Enter with or [Ok]. Print valid entry to Shell\n" "Blank line, after stripping, is ignored\n" diff -r 2adb8af9fffd Lib/idlelib/query.py --- a/Lib/idlelib/query.py Mon Jun 27 12:31:00 2016 -0700 +++ b/Lib/idlelib/query.py Mon Jun 27 22:26:27 2016 -0400 @@ -15,7 +15,8 @@ # of configSectionNameDialog.py (temporarily config_sec.py) into # generic and specific parts. -from tkinter import FALSE, TRUE, Toplevel +import importlib +from tkinter import Toplevel, StringVar from tkinter.messagebox import showerror from tkinter.ttk import Frame, Button, Entry, Label @@ -24,20 +25,22 @@ For this base class, accept any non-blank string. """ - def __init__(self, parent, title, message, - *, _htest=False, _utest=False): # Call from override. + def __init__(self, parent, title, message, text0='', + *, _htest=False, _utest=False): """Create popup, do not return until tk widget destroyed. - Additional subclass init must be done before calling this. + Additional subclass init must be done before calling this + unless _utest=True is passed to suppress wait_window(). title - string, title of popup dialog message - string, informational message to display + text0 - initial value for entry _htest - bool, change box location when running htest _utest - bool, leave window hidden and not modal """ Toplevel.__init__(self, parent) self.configure(borderwidth=5) - self.resizable(height=FALSE, width=FALSE) + self.resizable(height=False, width=False) self.title(title) self.transient(parent) self.grab_set() @@ -45,6 +48,7 @@ self.protocol("WM_DELETE_WINDOW", self.cancel) self.parent = parent self.message = message + self.text0 = text0 self.create_widgets() self.update_idletasks() #needs to be done here so that the winfo_reqwidth is valid @@ -62,19 +66,21 @@ self.wait_window() def create_widgets(self): # Call from override, if any. + # Bind widgets needed for entry_ok or unittest. frame = Frame(self, borderwidth=2, relief='sunken', ) label = Label(frame, anchor='w', justify='left', text=self.message) - self.entry = Entry(frame, width=30) # Bind name for entry_ok. + self.entryvar = StringVar(self, self.text0) + self.entry = Entry(frame, width=30, textvariable=self.entryvar) self.entry.focus_set() - buttons = Frame(self) # Bind buttons for invoke in unittest. + buttons = Frame(self) self.button_ok = Button(buttons, text='Ok', width=8, command=self.ok) self.button_cancel = Button(buttons, text='Cancel', width=8, command=self.cancel) - frame.pack(side='top', expand=TRUE, fill='both') + frame.pack(side='top', expand=True, fill='both') label.pack(padx=5, pady=5) self.entry.pack(padx=5, pady=5) buttons.pack(side='bottom') @@ -114,11 +120,9 @@ def __init__(self, parent, title, message, used_names, *, _htest=False, _utest=False): "used_names - collection of strings already in use" - self.used_names = used_names Query.__init__(self, parent, title, message, _htest=_htest, _utest=_utest) - # This call does ot return until tk widget is destroyed. def entry_ok(self): '''Stripping entered name, check that it is a sensible @@ -132,14 +136,54 @@ showerror(title='Name Error', message='Name too long. It should be no more than '+ '30 characters.', parent=self) - name = '' + return '' elif name in self.used_names: showerror(title='Name Error', message='This name is already in use.', parent=self) - name = '' + return '' return name +class ModuleName(Query): + "Get a module name for Open Module menu entry." + # Used in open_module (editor.EditorWindow until move to iobinding). + + def __init__(self, parent, title, message, text0='', + *, _htest=False, _utest=False): + """selname - name selected in text before Open Module invoked" + Pass _utest=True so can insert selname into self.entry. + """ + Query.__init__(self, parent, title, message, text0=text0, + _htest=_htest, _utest=_utest) + + def entry_ok(self): + name = self.entry.get().strip() + if not name: + return + # XXX Ought to insert current file's directory in front of path + try: + spec = importlib.util.find_spec(name) + except (ValueError, ImportError) as msg: + showerror("Import error", str(msg), parent=self) + return + if spec is None: + showerror("Import error", "module not found", + parent=self) + return + if not isinstance(spec.loader, importlib.abc.SourceLoader): + showerror("Import error", "not a source-based module", + parent=self) + return + try: + file_path = spec.loader.get_filename(name) + except AttributeError: + showerror("Import error", + "loader does not support get_filename", + parent=self) + return + return file_path + + if __name__ == '__main__': import unittest unittest.main('idlelib.idle_test.test_query', verbosity=2, exit=False)