Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0cd6b97

Browse files
committed
Issue 27437: Add query.ModuleName and use it for file => Load Module.
Users can now edit bad entries instead of starting over.
1 parent bae75cf commit 0cd6b97

5 files changed

Lines changed: 185 additions & 77 deletions

File tree

Lib/idlelib/README.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ config.py # Load, fetch, and save configuration (nim).
4141
configdialog.py # Display user configuration dialogs.
4242
config_help.py # Specify help source in configdialog.
4343
config_key.py # Change keybindings.
44-
config_sec.py # Spefify user config section name
4544
dynoption.py # Define mutable OptionMenu widget (nim).
4645
debugobj.py # Define class used in stackviewer.
4746
debugobj_r.py # Communicate objects between processes with rpc (nim).
@@ -66,6 +65,7 @@ pathbrowser.py # Create path browser window.
6665
percolator.py # Manage delegator stack (nim).
6766
pyparse.py # Give information on code indentation
6867
pyshell.py # Start IDLE, manage shell, complete editor window
68+
query.py # Query user for informtion
6969
redirector.py # Intercept widget subcommands (for percolator) (nim).
7070
replace.py # Search and replace pattern in text.
7171
rpc.py # Commuicate between idle and user processes (nim).
@@ -192,8 +192,8 @@ Options
192192
Configure IDLE # eEW.config_dialog, configdialog
193193
(tabs in the dialog)
194194
Font tab # config-main.def
195-
Highlight tab # config_sec, config-highlight.def
196-
Keys tab # config_key, configconfig_secg-keus.def
195+
Highlight tab # query, config-highlight.def
196+
Keys tab # query, config_key, config_keys.def
197197
General tab # config_help, config-main.def
198198
Extensions tab # config-extensions.def, corresponding .py
199199
---

Lib/idlelib/editor.py

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import webbrowser
1515

1616
from idlelib.multicall import MultiCallCreator
17+
from idlelib import query
1718
from idlelib import windows
1819
from idlelib import search
1920
from idlelib import grep
@@ -573,46 +574,27 @@ def goto_line_event(self, event):
573574
text.see("insert")
574575

575576
def open_module(self, event=None):
576-
# XXX Shouldn't this be in IOBinding?
577+
"""Get module name from user and open it.
578+
579+
Return module path or None for calls by open_class_browser
580+
when latter is not invoked in named editor window.
581+
"""
582+
# XXX This, open_class_browser, and open_path_browser
583+
# would fit better in iomenu.IOBinding.
577584
try:
578-
name = self.text.get("sel.first", "sel.last")
585+
name = self.text.get("sel.first", "sel.last").strip()
579586
except TclError:
580-
name = ""
581-
else:
582-
name = name.strip()
583-
name = tkSimpleDialog.askstring("Module",
584-
"Enter the name of a Python module\n"
585-
"to search on sys.path and open:",
586-
parent=self.text, initialvalue=name)
587-
if name:
588-
name = name.strip()
589-
if not name:
590-
return
591-
# XXX Ought to insert current file's directory in front of path
592-
try:
593-
spec = importlib.util.find_spec(name)
594-
except (ValueError, ImportError) as msg:
595-
tkMessageBox.showerror("Import error", str(msg), parent=self.text)
596-
return
597-
if spec is None:
598-
tkMessageBox.showerror("Import error", "module not found",
599-
parent=self.text)
600-
return
601-
if not isinstance(spec.loader, importlib.abc.SourceLoader):
602-
tkMessageBox.showerror("Import error", "not a source-based module",
603-
parent=self.text)
604-
return
605-
try:
606-
file_path = spec.loader.get_filename(name)
607-
except AttributeError:
608-
tkMessageBox.showerror("Import error",
609-
"loader does not support get_filename",
610-
parent=self.text)
611-
return
612-
if self.flist:
613-
self.flist.open(file_path)
614-
else:
615-
self.io.loadfile(file_path)
587+
name = ''
588+
file_path = query.ModuleName(
589+
self.text, "Open Module",
590+
"Enter the name of a Python module\n"
591+
"to search on sys.path and open:",
592+
name).result
593+
if file_path is not None:
594+
if self.flist:
595+
self.flist.open(file_path)
596+
else:
597+
self.io.loadfile(file_path)
616598
return file_path
617599

618600
def open_class_browser(self, event=None):

Lib/idlelib/idle_test/htest.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,9 @@ def _wrapper(parent): # htest #
235235

236236
Query_spec = {
237237
'file': 'query',
238-
'kwds': {'title':'Query',
239-
'message':'Enter something',
238+
'kwds': {'title': 'Query',
239+
'message': 'Enter something',
240+
'text0': 'Go',
240241
'_htest': True},
241242
'msg': "Enter with <Return> or [Ok]. Print valid entry to Shell\n"
242243
"Blank line, after stripping, is ignored\n"

Lib/idlelib/idle_test/test_query.py

Lines changed: 94 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
from unittest import mock
99
from idlelib.idle_test.mock_tk import Var, Mbox_func
1010
from idlelib import query
11-
Query, SectionName = query.Query, query.SectionName
1211

12+
Query = query.Query
1313
class Dummy_Query:
1414
# Mock for testing the following methods Query
1515
entry_ok = Query.entry_ok
@@ -23,7 +23,7 @@ def destroy(self):
2323
self.destroyed = True
2424

2525
# entry_ok calls modal messagebox.showerror if entry is not ok.
26-
# Mock showerrer returns, so don't need to click to continue.
26+
# Mock showerrer so don't need to click to continue.
2727
orig_showerror = query.showerror
2828
showerror = Mbox_func() # Instance has __call__ method.
2929

@@ -46,7 +46,7 @@ def test_blank_entry(self):
4646
dialog = self.dialog
4747
Equal = self.assertEqual
4848
dialog.entry.set(' ')
49-
Equal(dialog.entry_ok(), '')
49+
Equal(dialog.entry_ok(), None)
5050
Equal((dialog.result, dialog.destroyed), (None, False))
5151
Equal(showerror.title, 'Entry Error')
5252
self.assertIn('Blank', showerror.message)
@@ -74,58 +74,98 @@ def test_cancel(self):
7474

7575

7676
class Dummy_SectionName:
77-
# Mock for testing the following method of Section_Name
78-
entry_ok = SectionName.entry_ok
79-
# Attributes, constant or variable, needed for tests
77+
entry_ok = query.SectionName.entry_ok # Test override.
8078
used_names = ['used']
8179
entry = Var()
8280

8381
class SectionNameTest(unittest.TestCase):
8482
dialog = Dummy_SectionName()
8583

86-
8784
def setUp(self):
8885
showerror.title = None
8986

90-
def test_blank_name(self):
87+
def test_blank_section_name(self):
9188
dialog = self.dialog
9289
Equal = self.assertEqual
9390
dialog.entry.set(' ')
94-
Equal(dialog.entry_ok(), '')
91+
Equal(dialog.entry_ok(), None)
9592
Equal(showerror.title, 'Name Error')
9693
self.assertIn('No', showerror.message)
9794

98-
def test_used_name(self):
95+
def test_used_section_name(self):
9996
dialog = self.dialog
10097
Equal = self.assertEqual
10198
dialog.entry.set('used')
102-
Equal(self.dialog.entry_ok(), '')
99+
Equal(self.dialog.entry_ok(), None)
103100
Equal(showerror.title, 'Name Error')
104101
self.assertIn('use', showerror.message)
105102

106-
def test_long_name(self):
103+
def test_long_section_name(self):
107104
dialog = self.dialog
108105
Equal = self.assertEqual
109106
dialog.entry.set('good'*8)
110-
Equal(self.dialog.entry_ok(), '')
107+
Equal(self.dialog.entry_ok(), None)
111108
Equal(showerror.title, 'Name Error')
112109
self.assertIn('too long', showerror.message)
113110

114-
def test_good_entry(self):
111+
def test_good_section_name(self):
115112
dialog = self.dialog
116113
Equal = self.assertEqual
117114
dialog.entry.set(' good ')
118115
Equal(dialog.entry_ok(), 'good')
119116
Equal(showerror.title, None)
120117

121118

119+
class Dummy_ModuleName:
120+
entry_ok = query.ModuleName.entry_ok # Test override
121+
text0 = ''
122+
entry = Var()
123+
124+
class ModuleNameTest(unittest.TestCase):
125+
dialog = Dummy_ModuleName()
126+
127+
def setUp(self):
128+
showerror.title = None
129+
130+
def test_blank_module_name(self):
131+
dialog = self.dialog
132+
Equal = self.assertEqual
133+
dialog.entry.set(' ')
134+
Equal(dialog.entry_ok(), None)
135+
Equal(showerror.title, 'Name Error')
136+
self.assertIn('No', showerror.message)
137+
138+
def test_bogus_module_name(self):
139+
dialog = self.dialog
140+
Equal = self.assertEqual
141+
dialog.entry.set('__name_xyz123_should_not_exist__')
142+
Equal(self.dialog.entry_ok(), None)
143+
Equal(showerror.title, 'Import Error')
144+
self.assertIn('not found', showerror.message)
145+
146+
def test_c_source_name(self):
147+
dialog = self.dialog
148+
Equal = self.assertEqual
149+
dialog.entry.set('itertools')
150+
Equal(self.dialog.entry_ok(), None)
151+
Equal(showerror.title, 'Import Error')
152+
self.assertIn('source-based', showerror.message)
153+
154+
def test_good_module_name(self):
155+
dialog = self.dialog
156+
Equal = self.assertEqual
157+
dialog.entry.set('idlelib')
158+
self.assertTrue(dialog.entry_ok().endswith('__init__.py'))
159+
Equal(showerror.title, None)
160+
161+
122162
class QueryGuiTest(unittest.TestCase):
123163

124164
@classmethod
125165
def setUpClass(cls):
126166
requires('gui')
127-
cls.root = Tk()
128-
cls.dialog = Query(cls.root, 'TEST', 'test', _utest=True)
167+
cls.root = root = Tk()
168+
cls.dialog = Query(root, 'TEST', 'test', _utest=True)
129169
cls.dialog.destroy = mock.Mock()
130170

131171
@classmethod
@@ -160,5 +200,43 @@ def test_click_cancel(self):
160200
self.assertTrue(dialog.destroy.called)
161201

162202

203+
class SectionnameGuiTest(unittest.TestCase):
204+
205+
@classmethod
206+
def setUpClass(cls):
207+
requires('gui')
208+
209+
def test_click_section_name(self):
210+
root = Tk()
211+
dialog = query.SectionName(root, 'T', 't', {'abc'}, _utest=True)
212+
Equal = self.assertEqual
213+
Equal(dialog.used_names, {'abc'})
214+
dialog.entry.insert(0, 'okay')
215+
dialog.button_ok.invoke()
216+
Equal(dialog.result, 'okay')
217+
del dialog
218+
root.destroy()
219+
del root
220+
221+
222+
class ModulenameGuiTest(unittest.TestCase):
223+
224+
@classmethod
225+
def setUpClass(cls):
226+
requires('gui')
227+
228+
def test_click_module_name(self):
229+
root = Tk()
230+
dialog = query.ModuleName(root, 'T', 't', 'idlelib', _utest=True)
231+
Equal = self.assertEqual
232+
Equal(dialog.text0, 'idlelib')
233+
Equal(dialog.entry.get(), 'idlelib')
234+
dialog.button_ok.invoke()
235+
self.assertTrue(dialog.result.endswith('__init__.py'))
236+
del dialog
237+
root.destroy()
238+
del root
239+
240+
163241
if __name__ == '__main__':
164242
unittest.main(verbosity=2, exit=False)

0 commit comments

Comments
 (0)