mirror of
https://github.com/python/cpython.git
synced 2025-10-09 08:31:26 +00:00
Issue 27437: Add query.ModuleName and use it for file => Load Module.
Users can now edit bad entries instead of starting over.
This commit is contained in:
parent
bae75cf3fe
commit
0cd6b97701
5 changed files with 185 additions and 77 deletions
|
@ -41,7 +41,6 @@ config.py # Load, fetch, and save configuration (nim).
|
||||||
configdialog.py # Display user configuration dialogs.
|
configdialog.py # Display user configuration dialogs.
|
||||||
config_help.py # Specify help source in configdialog.
|
config_help.py # Specify help source in configdialog.
|
||||||
config_key.py # Change keybindings.
|
config_key.py # Change keybindings.
|
||||||
config_sec.py # Spefify user config section name
|
|
||||||
dynoption.py # Define mutable OptionMenu widget (nim).
|
dynoption.py # Define mutable OptionMenu widget (nim).
|
||||||
debugobj.py # Define class used in stackviewer.
|
debugobj.py # Define class used in stackviewer.
|
||||||
debugobj_r.py # Communicate objects between processes with rpc (nim).
|
debugobj_r.py # Communicate objects between processes with rpc (nim).
|
||||||
|
@ -66,6 +65,7 @@ pathbrowser.py # Create path browser window.
|
||||||
percolator.py # Manage delegator stack (nim).
|
percolator.py # Manage delegator stack (nim).
|
||||||
pyparse.py # Give information on code indentation
|
pyparse.py # Give information on code indentation
|
||||||
pyshell.py # Start IDLE, manage shell, complete editor window
|
pyshell.py # Start IDLE, manage shell, complete editor window
|
||||||
|
query.py # Query user for informtion
|
||||||
redirector.py # Intercept widget subcommands (for percolator) (nim).
|
redirector.py # Intercept widget subcommands (for percolator) (nim).
|
||||||
replace.py # Search and replace pattern in text.
|
replace.py # Search and replace pattern in text.
|
||||||
rpc.py # Commuicate between idle and user processes (nim).
|
rpc.py # Commuicate between idle and user processes (nim).
|
||||||
|
@ -192,8 +192,8 @@ Options
|
||||||
Configure IDLE # eEW.config_dialog, configdialog
|
Configure IDLE # eEW.config_dialog, configdialog
|
||||||
(tabs in the dialog)
|
(tabs in the dialog)
|
||||||
Font tab # config-main.def
|
Font tab # config-main.def
|
||||||
Highlight tab # config_sec, config-highlight.def
|
Highlight tab # query, config-highlight.def
|
||||||
Keys tab # config_key, configconfig_secg-keus.def
|
Keys tab # query, config_key, config_keys.def
|
||||||
General tab # config_help, config-main.def
|
General tab # config_help, config-main.def
|
||||||
Extensions tab # config-extensions.def, corresponding .py
|
Extensions tab # config-extensions.def, corresponding .py
|
||||||
---
|
---
|
||||||
|
|
|
@ -14,6 +14,7 @@ import traceback
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
from idlelib.multicall import MultiCallCreator
|
from idlelib.multicall import MultiCallCreator
|
||||||
|
from idlelib import query
|
||||||
from idlelib import windows
|
from idlelib import windows
|
||||||
from idlelib import search
|
from idlelib import search
|
||||||
from idlelib import grep
|
from idlelib import grep
|
||||||
|
@ -573,46 +574,27 @@ class EditorWindow(object):
|
||||||
text.see("insert")
|
text.see("insert")
|
||||||
|
|
||||||
def open_module(self, event=None):
|
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:
|
try:
|
||||||
name = self.text.get("sel.first", "sel.last")
|
name = self.text.get("sel.first", "sel.last").strip()
|
||||||
except TclError:
|
except TclError:
|
||||||
name = ""
|
name = ''
|
||||||
else:
|
file_path = query.ModuleName(
|
||||||
name = name.strip()
|
self.text, "Open Module",
|
||||||
name = tkSimpleDialog.askstring("Module",
|
"Enter the name of a Python module\n"
|
||||||
"Enter the name of a Python module\n"
|
"to search on sys.path and open:",
|
||||||
"to search on sys.path and open:",
|
name).result
|
||||||
parent=self.text, initialvalue=name)
|
if file_path is not None:
|
||||||
if name:
|
if self.flist:
|
||||||
name = name.strip()
|
self.flist.open(file_path)
|
||||||
if not name:
|
else:
|
||||||
return
|
self.io.loadfile(file_path)
|
||||||
# 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)
|
|
||||||
return file_path
|
return file_path
|
||||||
|
|
||||||
def open_class_browser(self, event=None):
|
def open_class_browser(self, event=None):
|
||||||
|
|
|
@ -235,8 +235,9 @@ _percolator_spec = {
|
||||||
|
|
||||||
Query_spec = {
|
Query_spec = {
|
||||||
'file': 'query',
|
'file': 'query',
|
||||||
'kwds': {'title':'Query',
|
'kwds': {'title': 'Query',
|
||||||
'message':'Enter something',
|
'message': 'Enter something',
|
||||||
|
'text0': 'Go',
|
||||||
'_htest': True},
|
'_htest': True},
|
||||||
'msg': "Enter with <Return> or [Ok]. Print valid entry to Shell\n"
|
'msg': "Enter with <Return> or [Ok]. Print valid entry to Shell\n"
|
||||||
"Blank line, after stripping, is ignored\n"
|
"Blank line, after stripping, is ignored\n"
|
||||||
|
|
|
@ -8,8 +8,8 @@ import unittest
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
from idlelib.idle_test.mock_tk import Var, Mbox_func
|
from idlelib.idle_test.mock_tk import Var, Mbox_func
|
||||||
from idlelib import query
|
from idlelib import query
|
||||||
Query, SectionName = query.Query, query.SectionName
|
|
||||||
|
|
||||||
|
Query = query.Query
|
||||||
class Dummy_Query:
|
class Dummy_Query:
|
||||||
# Mock for testing the following methods Query
|
# Mock for testing the following methods Query
|
||||||
entry_ok = Query.entry_ok
|
entry_ok = Query.entry_ok
|
||||||
|
@ -23,7 +23,7 @@ class Dummy_Query:
|
||||||
self.destroyed = True
|
self.destroyed = True
|
||||||
|
|
||||||
# entry_ok calls modal messagebox.showerror if entry is not ok.
|
# entry_ok calls modal messagebox.showerror if entry is not ok.
|
||||||
# Mock showerrer returns, so don't need to click to continue.
|
# Mock showerrer so don't need to click to continue.
|
||||||
orig_showerror = query.showerror
|
orig_showerror = query.showerror
|
||||||
showerror = Mbox_func() # Instance has __call__ method.
|
showerror = Mbox_func() # Instance has __call__ method.
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ class QueryTest(unittest.TestCase):
|
||||||
dialog = self.dialog
|
dialog = self.dialog
|
||||||
Equal = self.assertEqual
|
Equal = self.assertEqual
|
||||||
dialog.entry.set(' ')
|
dialog.entry.set(' ')
|
||||||
Equal(dialog.entry_ok(), '')
|
Equal(dialog.entry_ok(), None)
|
||||||
Equal((dialog.result, dialog.destroyed), (None, False))
|
Equal((dialog.result, dialog.destroyed), (None, False))
|
||||||
Equal(showerror.title, 'Entry Error')
|
Equal(showerror.title, 'Entry Error')
|
||||||
self.assertIn('Blank', showerror.message)
|
self.assertIn('Blank', showerror.message)
|
||||||
|
@ -74,44 +74,41 @@ class QueryTest(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class Dummy_SectionName:
|
class Dummy_SectionName:
|
||||||
# Mock for testing the following method of Section_Name
|
entry_ok = query.SectionName.entry_ok # Test override.
|
||||||
entry_ok = SectionName.entry_ok
|
|
||||||
# Attributes, constant or variable, needed for tests
|
|
||||||
used_names = ['used']
|
used_names = ['used']
|
||||||
entry = Var()
|
entry = Var()
|
||||||
|
|
||||||
class SectionNameTest(unittest.TestCase):
|
class SectionNameTest(unittest.TestCase):
|
||||||
dialog = Dummy_SectionName()
|
dialog = Dummy_SectionName()
|
||||||
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
showerror.title = None
|
showerror.title = None
|
||||||
|
|
||||||
def test_blank_name(self):
|
def test_blank_section_name(self):
|
||||||
dialog = self.dialog
|
dialog = self.dialog
|
||||||
Equal = self.assertEqual
|
Equal = self.assertEqual
|
||||||
dialog.entry.set(' ')
|
dialog.entry.set(' ')
|
||||||
Equal(dialog.entry_ok(), '')
|
Equal(dialog.entry_ok(), None)
|
||||||
Equal(showerror.title, 'Name Error')
|
Equal(showerror.title, 'Name Error')
|
||||||
self.assertIn('No', showerror.message)
|
self.assertIn('No', showerror.message)
|
||||||
|
|
||||||
def test_used_name(self):
|
def test_used_section_name(self):
|
||||||
dialog = self.dialog
|
dialog = self.dialog
|
||||||
Equal = self.assertEqual
|
Equal = self.assertEqual
|
||||||
dialog.entry.set('used')
|
dialog.entry.set('used')
|
||||||
Equal(self.dialog.entry_ok(), '')
|
Equal(self.dialog.entry_ok(), None)
|
||||||
Equal(showerror.title, 'Name Error')
|
Equal(showerror.title, 'Name Error')
|
||||||
self.assertIn('use', showerror.message)
|
self.assertIn('use', showerror.message)
|
||||||
|
|
||||||
def test_long_name(self):
|
def test_long_section_name(self):
|
||||||
dialog = self.dialog
|
dialog = self.dialog
|
||||||
Equal = self.assertEqual
|
Equal = self.assertEqual
|
||||||
dialog.entry.set('good'*8)
|
dialog.entry.set('good'*8)
|
||||||
Equal(self.dialog.entry_ok(), '')
|
Equal(self.dialog.entry_ok(), None)
|
||||||
Equal(showerror.title, 'Name Error')
|
Equal(showerror.title, 'Name Error')
|
||||||
self.assertIn('too long', showerror.message)
|
self.assertIn('too long', showerror.message)
|
||||||
|
|
||||||
def test_good_entry(self):
|
def test_good_section_name(self):
|
||||||
dialog = self.dialog
|
dialog = self.dialog
|
||||||
Equal = self.assertEqual
|
Equal = self.assertEqual
|
||||||
dialog.entry.set(' good ')
|
dialog.entry.set(' good ')
|
||||||
|
@ -119,13 +116,56 @@ class SectionNameTest(unittest.TestCase):
|
||||||
Equal(showerror.title, None)
|
Equal(showerror.title, None)
|
||||||
|
|
||||||
|
|
||||||
|
class Dummy_ModuleName:
|
||||||
|
entry_ok = query.ModuleName.entry_ok # Test override
|
||||||
|
text0 = ''
|
||||||
|
entry = Var()
|
||||||
|
|
||||||
|
class ModuleNameTest(unittest.TestCase):
|
||||||
|
dialog = Dummy_ModuleName()
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
showerror.title = None
|
||||||
|
|
||||||
|
def test_blank_module_name(self):
|
||||||
|
dialog = self.dialog
|
||||||
|
Equal = self.assertEqual
|
||||||
|
dialog.entry.set(' ')
|
||||||
|
Equal(dialog.entry_ok(), None)
|
||||||
|
Equal(showerror.title, 'Name Error')
|
||||||
|
self.assertIn('No', showerror.message)
|
||||||
|
|
||||||
|
def test_bogus_module_name(self):
|
||||||
|
dialog = self.dialog
|
||||||
|
Equal = self.assertEqual
|
||||||
|
dialog.entry.set('__name_xyz123_should_not_exist__')
|
||||||
|
Equal(self.dialog.entry_ok(), None)
|
||||||
|
Equal(showerror.title, 'Import Error')
|
||||||
|
self.assertIn('not found', showerror.message)
|
||||||
|
|
||||||
|
def test_c_source_name(self):
|
||||||
|
dialog = self.dialog
|
||||||
|
Equal = self.assertEqual
|
||||||
|
dialog.entry.set('itertools')
|
||||||
|
Equal(self.dialog.entry_ok(), None)
|
||||||
|
Equal(showerror.title, 'Import Error')
|
||||||
|
self.assertIn('source-based', showerror.message)
|
||||||
|
|
||||||
|
def test_good_module_name(self):
|
||||||
|
dialog = self.dialog
|
||||||
|
Equal = self.assertEqual
|
||||||
|
dialog.entry.set('idlelib')
|
||||||
|
self.assertTrue(dialog.entry_ok().endswith('__init__.py'))
|
||||||
|
Equal(showerror.title, None)
|
||||||
|
|
||||||
|
|
||||||
class QueryGuiTest(unittest.TestCase):
|
class QueryGuiTest(unittest.TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
requires('gui')
|
requires('gui')
|
||||||
cls.root = Tk()
|
cls.root = root = Tk()
|
||||||
cls.dialog = Query(cls.root, 'TEST', 'test', _utest=True)
|
cls.dialog = Query(root, 'TEST', 'test', _utest=True)
|
||||||
cls.dialog.destroy = mock.Mock()
|
cls.dialog.destroy = mock.Mock()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -160,5 +200,43 @@ class QueryGuiTest(unittest.TestCase):
|
||||||
self.assertTrue(dialog.destroy.called)
|
self.assertTrue(dialog.destroy.called)
|
||||||
|
|
||||||
|
|
||||||
|
class SectionnameGuiTest(unittest.TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
requires('gui')
|
||||||
|
|
||||||
|
def test_click_section_name(self):
|
||||||
|
root = Tk()
|
||||||
|
dialog = query.SectionName(root, 'T', 't', {'abc'}, _utest=True)
|
||||||
|
Equal = self.assertEqual
|
||||||
|
Equal(dialog.used_names, {'abc'})
|
||||||
|
dialog.entry.insert(0, 'okay')
|
||||||
|
dialog.button_ok.invoke()
|
||||||
|
Equal(dialog.result, 'okay')
|
||||||
|
del dialog
|
||||||
|
root.destroy()
|
||||||
|
del root
|
||||||
|
|
||||||
|
|
||||||
|
class ModulenameGuiTest(unittest.TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
requires('gui')
|
||||||
|
|
||||||
|
def test_click_module_name(self):
|
||||||
|
root = Tk()
|
||||||
|
dialog = query.ModuleName(root, 'T', 't', 'idlelib', _utest=True)
|
||||||
|
Equal = self.assertEqual
|
||||||
|
Equal(dialog.text0, 'idlelib')
|
||||||
|
Equal(dialog.entry.get(), 'idlelib')
|
||||||
|
dialog.button_ok.invoke()
|
||||||
|
self.assertTrue(dialog.result.endswith('__init__.py'))
|
||||||
|
del dialog
|
||||||
|
root.destroy()
|
||||||
|
del root
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(verbosity=2, exit=False)
|
unittest.main(verbosity=2, exit=False)
|
||||||
|
|
|
@ -15,7 +15,8 @@ Configdialog uses it for new highlight theme and keybinding set names.
|
||||||
# of configSectionNameDialog.py (temporarily config_sec.py) into
|
# of configSectionNameDialog.py (temporarily config_sec.py) into
|
||||||
# generic and specific parts.
|
# generic and specific parts.
|
||||||
|
|
||||||
from tkinter import FALSE, TRUE, Toplevel
|
import importlib
|
||||||
|
from tkinter import Toplevel, StringVar
|
||||||
from tkinter.messagebox import showerror
|
from tkinter.messagebox import showerror
|
||||||
from tkinter.ttk import Frame, Button, Entry, Label
|
from tkinter.ttk import Frame, Button, Entry, Label
|
||||||
|
|
||||||
|
@ -24,20 +25,22 @@ class Query(Toplevel):
|
||||||
|
|
||||||
For this base class, accept any non-blank string.
|
For this base class, accept any non-blank string.
|
||||||
"""
|
"""
|
||||||
def __init__(self, parent, title, message,
|
def __init__(self, parent, title, message, text0='',
|
||||||
*, _htest=False, _utest=False): # Call from override.
|
*, _htest=False, _utest=False):
|
||||||
"""Create popup, do not return until tk widget destroyed.
|
"""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
|
title - string, title of popup dialog
|
||||||
message - string, informational message to display
|
message - string, informational message to display
|
||||||
|
text0 - initial value for entry
|
||||||
_htest - bool, change box location when running htest
|
_htest - bool, change box location when running htest
|
||||||
_utest - bool, leave window hidden and not modal
|
_utest - bool, leave window hidden and not modal
|
||||||
"""
|
"""
|
||||||
Toplevel.__init__(self, parent)
|
Toplevel.__init__(self, parent)
|
||||||
self.configure(borderwidth=5)
|
self.configure(borderwidth=5)
|
||||||
self.resizable(height=FALSE, width=FALSE)
|
self.resizable(height=False, width=False)
|
||||||
self.title(title)
|
self.title(title)
|
||||||
self.transient(parent)
|
self.transient(parent)
|
||||||
self.grab_set()
|
self.grab_set()
|
||||||
|
@ -45,6 +48,7 @@ class Query(Toplevel):
|
||||||
self.protocol("WM_DELETE_WINDOW", self.cancel)
|
self.protocol("WM_DELETE_WINDOW", self.cancel)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.message = message
|
self.message = message
|
||||||
|
self.text0 = text0
|
||||||
self.create_widgets()
|
self.create_widgets()
|
||||||
self.update_idletasks()
|
self.update_idletasks()
|
||||||
#needs to be done here so that the winfo_reqwidth is valid
|
#needs to be done here so that the winfo_reqwidth is valid
|
||||||
|
@ -62,31 +66,34 @@ class Query(Toplevel):
|
||||||
self.wait_window()
|
self.wait_window()
|
||||||
|
|
||||||
def create_widgets(self): # Call from override, if any.
|
def create_widgets(self): # Call from override, if any.
|
||||||
|
# Bind widgets needed for entry_ok or unittest to self.
|
||||||
frame = Frame(self, borderwidth=2, relief='sunken', )
|
frame = Frame(self, borderwidth=2, relief='sunken', )
|
||||||
label = Label(frame, anchor='w', justify='left',
|
label = Label(frame, anchor='w', justify='left',
|
||||||
text=self.message)
|
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()
|
self.entry.focus_set()
|
||||||
|
|
||||||
buttons = Frame(self) # Bind buttons for invoke in unittest.
|
buttons = Frame(self)
|
||||||
self.button_ok = Button(buttons, text='Ok',
|
self.button_ok = Button(buttons, text='Ok',
|
||||||
width=8, command=self.ok)
|
width=8, command=self.ok)
|
||||||
self.button_cancel = Button(buttons, text='Cancel',
|
self.button_cancel = Button(buttons, text='Cancel',
|
||||||
width=8, command=self.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)
|
label.pack(padx=5, pady=5)
|
||||||
self.entry.pack(padx=5, pady=5)
|
self.entry.pack(padx=5, pady=5)
|
||||||
buttons.pack(side='bottom')
|
buttons.pack(side='bottom')
|
||||||
self.button_ok.pack(side='left', padx=5)
|
self.button_ok.pack(side='left', padx=5)
|
||||||
self.button_cancel.pack(side='right', padx=5)
|
self.button_cancel.pack(side='right', padx=5)
|
||||||
|
|
||||||
def entry_ok(self): # Usually replace.
|
def entry_ok(self): # Example: usually replace.
|
||||||
"Check that entry not blank."
|
"Return non-blank entry or None."
|
||||||
entry = self.entry.get().strip()
|
entry = self.entry.get().strip()
|
||||||
if not entry:
|
if not entry:
|
||||||
showerror(title='Entry Error',
|
showerror(title='Entry Error',
|
||||||
message='Blank line.', parent=self)
|
message='Blank line.', parent=self)
|
||||||
|
return
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
def ok(self, event=None): # Do not replace.
|
def ok(self, event=None): # Do not replace.
|
||||||
|
@ -95,7 +102,7 @@ class Query(Toplevel):
|
||||||
Otherwise leave dialog open for user to correct entry or cancel.
|
Otherwise leave dialog open for user to correct entry or cancel.
|
||||||
'''
|
'''
|
||||||
entry = self.entry_ok()
|
entry = self.entry_ok()
|
||||||
if entry:
|
if entry is not None:
|
||||||
self.result = entry
|
self.result = entry
|
||||||
self.destroy()
|
self.destroy()
|
||||||
else:
|
else:
|
||||||
|
@ -114,32 +121,72 @@ class SectionName(Query):
|
||||||
def __init__(self, parent, title, message, used_names,
|
def __init__(self, parent, title, message, used_names,
|
||||||
*, _htest=False, _utest=False):
|
*, _htest=False, _utest=False):
|
||||||
"used_names - collection of strings already in use"
|
"used_names - collection of strings already in use"
|
||||||
|
|
||||||
self.used_names = used_names
|
self.used_names = used_names
|
||||||
Query.__init__(self, parent, title, message,
|
Query.__init__(self, parent, title, message,
|
||||||
_htest=_htest, _utest=_utest)
|
_htest=_htest, _utest=_utest)
|
||||||
# This call does ot return until tk widget is destroyed.
|
|
||||||
|
|
||||||
def entry_ok(self):
|
def entry_ok(self):
|
||||||
'''Stripping entered name, check that it is a sensible
|
"Return sensible ConfigParser section name or None."
|
||||||
ConfigParser file section name. Return it if it is, '' if not.
|
|
||||||
'''
|
|
||||||
name = self.entry.get().strip()
|
name = self.entry.get().strip()
|
||||||
if not name:
|
if not name:
|
||||||
showerror(title='Name Error',
|
showerror(title='Name Error',
|
||||||
message='No name specified.', parent=self)
|
message='No name specified.', parent=self)
|
||||||
|
return
|
||||||
elif len(name)>30:
|
elif len(name)>30:
|
||||||
showerror(title='Name Error',
|
showerror(title='Name Error',
|
||||||
message='Name too long. It should be no more than '+
|
message='Name too long. It should be no more than '+
|
||||||
'30 characters.', parent=self)
|
'30 characters.', parent=self)
|
||||||
name = ''
|
return
|
||||||
elif name in self.used_names:
|
elif name in self.used_names:
|
||||||
showerror(title='Name Error',
|
showerror(title='Name Error',
|
||||||
message='This name is already in use.', parent=self)
|
message='This name is already in use.', parent=self)
|
||||||
name = ''
|
return
|
||||||
return name
|
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):
|
||||||
|
"""text0 - name selected in text before Open Module invoked"
|
||||||
|
"""
|
||||||
|
Query.__init__(self, parent, title, message, text0=text0,
|
||||||
|
_htest=_htest, _utest=_utest)
|
||||||
|
|
||||||
|
def entry_ok(self):
|
||||||
|
"Return entered module name as file path or None."
|
||||||
|
# Moved here from Editor_Window.load_module 2016 July.
|
||||||
|
name = self.entry.get().strip()
|
||||||
|
if not name:
|
||||||
|
showerror(title='Name Error',
|
||||||
|
message='No name specified.', parent=self)
|
||||||
|
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__':
|
if __name__ == '__main__':
|
||||||
import unittest
|
import unittest
|
||||||
unittest.main('idlelib.idle_test.test_query', verbosity=2, exit=False)
|
unittest.main('idlelib.idle_test.test_query', verbosity=2, exit=False)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue