From ffc22b8bd02d159c29697e2857707461e689183e Mon Sep 17 00:00:00 2001 From: Cheryl Sabella Date: Sun, 2 Jun 2019 20:34:38 -0400 Subject: [PATCH 01/17] bpo-5680: IDLE: Run modules with command line arguments --- Doc/library/idle.rst | 15 ++++++++- Lib/idlelib/config-keys.def | 5 +++ Lib/idlelib/config.py | 1 + Lib/idlelib/editor.py | 1 + Lib/idlelib/idle_test/htest.py | 10 ++++++ Lib/idlelib/idle_test/test_query.py | 49 +++++++++++++++++++++++++++++ Lib/idlelib/mainmenu.py | 1 + Lib/idlelib/query.py | 24 +++++++++++++- Lib/idlelib/runscript.py | 22 ++++++++++--- 9 files changed, 121 insertions(+), 7 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index bd24695c728233..d762e4b957f5a0 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -207,9 +207,13 @@ Strip trailing whitespace Run menu (Editor window only) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. _python-shell: + Python Shell Open or wake up the Python Shell window. +.. _check-module: + Check Module Check the syntax of the module currently open in the Editor window. If the module has not been saved IDLE will either prompt the user to save or @@ -217,8 +221,10 @@ Check Module there is a syntax error, the approximate location is indicated in the Editor window. +.. _run-module: + Run Module - Do Check Module (above). If no error, restart the shell to clean the + Do :ref:`Check Module `. If no error, restart the shell toclean the environment, then execute the module. Output is displayed in the Shell window. Note that output requires use of ``print`` or ``write``. When execution is complete, the Shell retains focus and displays a prompt. @@ -226,6 +232,13 @@ Run Module This is similar to executing a file with ``python -i file`` at a command line. +.. _run-module-with-arguments: + +Run Module with Arguments + Same as :ref:`Run Module `, except allow entry of the + command line arguments that are passed to the module. This is similar + to executing a file with ``python -i file [args]`` at a command line. + Shell menu (Shell window only) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/idlelib/config-keys.def b/Lib/idlelib/config-keys.def index fd235194dfc950..1edcdc02a5d055 100644 --- a/Lib/idlelib/config-keys.def +++ b/Lib/idlelib/config-keys.def @@ -63,6 +63,7 @@ force-open-calltip= format-paragraph= flash-paren= run-module= +run-module-arguments= check-module= zoom-height= @@ -122,6 +123,7 @@ force-open-calltip= format-paragraph= flash-paren= run-module= +run-module-arguments= check-module= zoom-height= @@ -181,6 +183,7 @@ force-open-calltip= format-paragraph= flash-paren= run-module= +run-module-arguments= check-module= zoom-height= @@ -240,6 +243,7 @@ force-open-calltip= format-paragraph= flash-paren= run-module= +run-module-arguments= check-module= zoom-height= @@ -300,5 +304,6 @@ force-open-calltip= format-paragraph= flash-paren= run-module= +run-module-arguments= check-module= zoom-height= diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index aa94d6535be6bb..871fbbaf064c9b 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -658,6 +658,7 @@ def GetCoreKeys(self, keySetName=None): '<>': [''], '<>': [''], '<>': [''], + '<>': [''], '<>': [''], '<>': [''], } diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 89b7239a96ea0e..781966dd1248e6 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -304,6 +304,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): scriptbinding = ScriptBinding(self) text.bind("<>", scriptbinding.check_module_event) text.bind("<>", scriptbinding.run_module_event) + text.bind("<>", scriptbinding.run_module_arguments_event) text.bind("<>", self.Rstrip(self).do_rstrip) ctip = self.Calltip(self) text.bind("<>", ctip.try_open_calltip_event) diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py index 429081f7ef25a8..0552e1f816b36e 100644 --- a/Lib/idlelib/idle_test/htest.py +++ b/Lib/idlelib/idle_test/htest.py @@ -108,6 +108,16 @@ def _wrapper(parent): # htest # "The default color scheme is in idlelib/config-highlight.def" } +CommandLineArgs_spec = { + 'file': 'query', + 'kwds': {'title': 'Command Line Args', + 'message': 'Enter command line arguments', + '_htest': True}, + 'msg': "Enter with or [Ok]. Print valid entry to Shell\n" + "Arguments are parsed into a list\n" + "Close dialog with valid entry, , [Cancel], [X]" + } + ConfigDialog_spec = { 'file': 'configdialog', 'kwds': {'title': 'ConfigDialogTest', diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py index c1c4a25cc50608..aa51e32202236b 100644 --- a/Lib/idlelib/idle_test/test_query.py +++ b/Lib/idlelib/idle_test/test_query.py @@ -242,6 +242,36 @@ def test_entry_ok_helpsource(self): self.assertEqual(dialog.entry_ok(), result) +class CommandLineArgsTest(unittest.TestCase): + "Test CommandLineArgs subclass of Query." + + class Dummy_CommandLineArgs: + entry_ok = query.CommandLineArgs.entry_ok # Function being tested. + entry = Var() + entry_error = {} + def __init__(self, dummy_entry): + self.entry.set(dummy_entry) + self.entry_error['text'] = '' + def showerror(self, message): + self.entry_error['text'] = message + + def test_blank_args(self): + dialog = self.Dummy_CommandLineArgs(' ') + self.assertEqual(dialog.entry_ok(), None) + self.assertIn('no arguments', dialog.entry_error['text']) + + def test_invalid_args(self): + dialog = self.Dummy_CommandLineArgs("'no-closing-quote") + self.assertEqual(dialog.entry_ok(), None) + self.assertIn('No closing', dialog.entry_error['text']) + + def test_good_args(self): + dialog = self.Dummy_CommandLineArgs('-n 10 --verbose -p /path --name "my name"') + self.assertEqual(dialog.entry_ok(), + ['-n', '10', '--verbose', '-p', '/path', '--name', 'my name']) + self.assertEqual(dialog.entry_error['text'], '') + + # GUI TESTS class QueryGuiTest(unittest.TestCase): @@ -348,5 +378,24 @@ def test_click_help_source(self): del root +class CommandLineArgsGuiTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + + def test_click_args(self): + root = Tk() + root.withdraw() + dialog = query.CommandLineArgs(root, 'Title', 'message', _utest=True) + Equal = self.assertEqual + dialog.entry.insert(0, 'okay') + dialog.button_ok.invoke() + self.assertEqual(dialog.result, ['okay']) + del dialog + root.destroy() + del root + + if __name__ == '__main__': unittest.main(verbosity=2, exit=False) diff --git a/Lib/idlelib/mainmenu.py b/Lib/idlelib/mainmenu.py index f834220fc2bb75..6f36016296e933 100644 --- a/Lib/idlelib/mainmenu.py +++ b/Lib/idlelib/mainmenu.py @@ -76,6 +76,7 @@ ('Python Shell', '<>'), ('C_heck Module', '<>'), ('R_un Module', '<>'), + ('Run Module with _Arguments', '<>'), ]), ('shell', [ diff --git a/Lib/idlelib/query.py b/Lib/idlelib/query.py index f0b72553db87f7..27e0031f8942a6 100644 --- a/Lib/idlelib/query.py +++ b/Lib/idlelib/query.py @@ -21,6 +21,7 @@ import importlib import os +import shlex from sys import executable, platform # Platform is set for one test. from tkinter import Toplevel, StringVar, W, E, S @@ -302,10 +303,31 @@ def entry_ok(self): path = self.path_ok() return None if name is None or path is None else (name, path) +class CommandLineArgs(Query): + "Get a list of parsed command line arguments." + # Used in runscript.run_module_arguments_event + + def __init__(self, parent, title, message, *, _htest=False, _utest=False): + super().__init__(parent, title, message, _htest=_htest, _utest=_utest) + + def entry_ok(self): + "Return list of parsed arguments or None." + self.entry_error['text'] = '' + cli_args = self.entry.get().strip() + if not cli_args: + self.showerror('no arguments specified.') + return None + try: + lex = shlex.split(cli_args, posix=True) + except ValueError as err: + self.showerror(str(err)) + return None + return lex + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_query', verbosity=2, exit=False) from idlelib.idle_test.htest import run - run(Query, HelpSource) + run(Query, HelpSource, CommandLineArgs) diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py index 83433b1cf0a459..eefacc0efd1cab 100644 --- a/Lib/idlelib/runscript.py +++ b/Lib/idlelib/runscript.py @@ -18,6 +18,7 @@ from idlelib.config import idleConf from idlelib import macosx from idlelib import pyshell +from idlelib.query import CommandLineArgs indent_message = """Error: Inconsistent indentation detected! @@ -113,7 +114,16 @@ def run_module_event(self, event): else: return self._run_module_event(event) - def _run_module_event(self, event): + def run_module_arguments_event(self, event): + cli_args = CommandLineArgs( + event.widget, "Run with Arguments", + "Command line argunments:").result + # User cancelled. + if not cli_args: + return 'break' + return self._run_module_event(event, cli_args) + + def _run_module_event(self, event, cli_args=None): """Run the module after setting up the environment. First check the syntax. If OK, make sure the shell is active and @@ -121,7 +131,6 @@ def _run_module_event(self, event): directory to the directory of the module being executed and also add that directory to its sys.path if not already included. """ - filename = self.getfilename() if not filename: return 'break' @@ -136,17 +145,20 @@ def _run_module_event(self, event): self.editwin._filename_to_unicode(filename)) dirname = os.path.dirname(filename) # XXX Too often this discards arguments the user just set... - interp.runcommand("""if 1: + argv = [filename] + if cli_args: + argv += cli_args + interp.runcommand(f"""if 1: __file__ = {filename!r} import sys as _sys from os.path import basename as _basename if (not _sys.argv or _basename(_sys.argv[0]) != _basename(__file__)): - _sys.argv = [__file__] + _sys.argv = {argv!r} import os as _os _os.chdir({dirname!r}) del _sys, _basename, _os - \n""".format(filename=filename, dirname=dirname)) + \n""") interp.prepend_syspath(filename) # XXX KBK 03Jul04 When run w/o subprocess, runtime warnings still # go to __stderr__. With subprocess, they go to the shell. From 36f7771d44d26353ff4d4011019c41e5877209b9 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" Date: Mon, 3 Jun 2019 00:39:30 +0000 Subject: [PATCH 02/17] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Misc/NEWS.d/next/IDLE/2019-06-03-00-39-29.bpo-5680.VCQfOO.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/IDLE/2019-06-03-00-39-29.bpo-5680.VCQfOO.rst diff --git a/Misc/NEWS.d/next/IDLE/2019-06-03-00-39-29.bpo-5680.VCQfOO.rst b/Misc/NEWS.d/next/IDLE/2019-06-03-00-39-29.bpo-5680.VCQfOO.rst new file mode 100644 index 00000000000000..199055dfd5a99f --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-06-03-00-39-29.bpo-5680.VCQfOO.rst @@ -0,0 +1 @@ +Run modules from the editor using command line arguments. \ No newline at end of file From 69cf1b687dfe1bc1da6fe70b51875f93ade61503 Mon Sep 17 00:00:00 2001 From: Cheryl Sabella Date: Sun, 2 Jun 2019 21:03:43 -0400 Subject: [PATCH 03/17] Fix editing error --- Doc/library/idle.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index d762e4b957f5a0..8f984ee3fc4040 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -224,7 +224,7 @@ Check Module .. _run-module: Run Module - Do :ref:`Check Module `. If no error, restart the shell toclean the + Do :ref:`Check Module `. If no error, restart the shell to clean the environment, then execute the module. Output is displayed in the Shell window. Note that output requires use of ``print`` or ``write``. When execution is complete, the Shell retains focus and displays a prompt. From dbdd58076c8a04b58d2c00bafd90336429e1abd3 Mon Sep 17 00:00:00 2001 From: Cheryl Sabella Date: Mon, 3 Jun 2019 18:22:51 -0400 Subject: [PATCH 04/17] Create more generic dialog and change keybinding --- Doc/library/idle.rst | 14 +++++--- Lib/idlelib/config-keys.def | 10 +++--- Lib/idlelib/config.py | 2 +- Lib/idlelib/editor.py | 2 +- Lib/idlelib/idle_test/htest.py | 5 ++- Lib/idlelib/idle_test/test_query.py | 48 +++++++++++++++++-------- Lib/idlelib/mainmenu.py | 2 +- Lib/idlelib/query.py | 56 ++++++++++++++++++++++------- Lib/idlelib/runscript.py | 24 ++++++------- 9 files changed, 108 insertions(+), 55 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index 8f984ee3fc4040..4eca68d2958cc9 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -232,12 +232,16 @@ Run Module This is similar to executing a file with ``python -i file`` at a command line. -.. _run-module-with-arguments: +.. _run-custom: + +Run Custom + Same as :ref:`Run Module `, except allow customization of the + environment used when running the module. + + The *Command Line Arguments* are passed to the module like :data:`sys.argv` + arguments would be from the command line. This is similar to executing a + file with ``python -i file [args]``. -Run Module with Arguments - Same as :ref:`Run Module `, except allow entry of the - command line arguments that are passed to the module. This is similar - to executing a file with ``python -i file [args]`` at a command line. Shell menu (Shell window only) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/idlelib/config-keys.def b/Lib/idlelib/config-keys.def index 1edcdc02a5d055..f71269b5b49f46 100644 --- a/Lib/idlelib/config-keys.def +++ b/Lib/idlelib/config-keys.def @@ -63,7 +63,7 @@ force-open-calltip= format-paragraph= flash-paren= run-module= -run-module-arguments= +run-custom= check-module= zoom-height= @@ -123,7 +123,7 @@ force-open-calltip= format-paragraph= flash-paren= run-module= -run-module-arguments= +run-custom= check-module= zoom-height= @@ -183,7 +183,7 @@ force-open-calltip= format-paragraph= flash-paren= run-module= -run-module-arguments= +run-custom= check-module= zoom-height= @@ -243,7 +243,7 @@ force-open-calltip= format-paragraph= flash-paren= run-module= -run-module-arguments= +run-custom= check-module= zoom-height= @@ -304,6 +304,6 @@ force-open-calltip= format-paragraph= flash-paren= run-module= -run-module-arguments= +run-custom= check-module= zoom-height= diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 871fbbaf064c9b..fcde3da1d570cb 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -658,7 +658,7 @@ def GetCoreKeys(self, keySetName=None): '<>': [''], '<>': [''], '<>': [''], - '<>': [''], + '<>': [''], '<>': [''], '<>': [''], } diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 781966dd1248e6..29c965d6805fff 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -304,7 +304,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): scriptbinding = ScriptBinding(self) text.bind("<>", scriptbinding.check_module_event) text.bind("<>", scriptbinding.run_module_event) - text.bind("<>", scriptbinding.run_module_arguments_event) + text.bind("<>", scriptbinding.run_custom_event) text.bind("<>", self.Rstrip(self).do_rstrip) ctip = self.Calltip(self) text.bind("<>", ctip.try_open_calltip_event) diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py index 0552e1f816b36e..e5a3da74de9304 100644 --- a/Lib/idlelib/idle_test/htest.py +++ b/Lib/idlelib/idle_test/htest.py @@ -108,10 +108,9 @@ def _wrapper(parent): # htest # "The default color scheme is in idlelib/config-highlight.def" } -CommandLineArgs_spec = { +CustomRun_spec = { 'file': 'query', - 'kwds': {'title': 'Command Line Args', - 'message': 'Enter command line arguments', + 'kwds': {'title': 'Custom Run Args', '_htest': True}, 'msg': "Enter with or [Ok]. Print valid entry to Shell\n" "Arguments are parsed into a list\n" diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py index aa51e32202236b..9decedea40398c 100644 --- a/Lib/idlelib/idle_test/test_query.py +++ b/Lib/idlelib/idle_test/test_query.py @@ -242,11 +242,11 @@ def test_entry_ok_helpsource(self): self.assertEqual(dialog.entry_ok(), result) -class CommandLineArgsTest(unittest.TestCase): - "Test CommandLineArgs subclass of Query." +class CustomRunCLIargsokTest(unittest.TestCase): + "Test cli_ok method of the CustomRun subclass of Query." - class Dummy_CommandLineArgs: - entry_ok = query.CommandLineArgs.entry_ok # Function being tested. + class Dummy_CustomRun: + cli_args_ok = query.CustomRun.cli_args_ok # Function being tested. entry = Var() entry_error = {} def __init__(self, dummy_entry): @@ -256,22 +256,43 @@ def showerror(self, message): self.entry_error['text'] = message def test_blank_args(self): - dialog = self.Dummy_CommandLineArgs(' ') - self.assertEqual(dialog.entry_ok(), None) + dialog = self.Dummy_CustomRun(' ') + self.assertEqual(dialog.cli_args_ok(), None) self.assertIn('no arguments', dialog.entry_error['text']) def test_invalid_args(self): - dialog = self.Dummy_CommandLineArgs("'no-closing-quote") - self.assertEqual(dialog.entry_ok(), None) + dialog = self.Dummy_CustomRun("'no-closing-quote") + self.assertEqual(dialog.cli_args_ok(), None) self.assertIn('No closing', dialog.entry_error['text']) def test_good_args(self): - dialog = self.Dummy_CommandLineArgs('-n 10 --verbose -p /path --name "my name"') - self.assertEqual(dialog.entry_ok(), + dialog = self.Dummy_CustomRun('-n 10 --verbose -p /path --name "my name"') + self.assertEqual(dialog.cli_args_ok(), ['-n', '10', '--verbose', '-p', '/path', '--name', 'my name']) self.assertEqual(dialog.entry_error['text'], '') +class CustomRunEntryokTest(unittest.TestCase): + "Test entry_ok method of the CustomRun subclass of Query." + + class Dummy_CustomRun: + entry_ok = query.CustomRun.entry_ok + entry_error = {} + def cli_args_ok(self): + return self.cli_args + def restart_ok(self): + return self.restart + + def test_entry_ok_customrun(self): + dialog = self.Dummy_CustomRun() + for dialog.restart in {True, False}: + for cli_args, result in ((None, None), + ('my arg', ('my arg', dialog.restart))): + with self.subTest(): + dialog.cli_args = cli_args + self.assertEqual(dialog.entry_ok(), result) + + # GUI TESTS class QueryGuiTest(unittest.TestCase): @@ -378,7 +399,7 @@ def test_click_help_source(self): del root -class CommandLineArgsGuiTest(unittest.TestCase): +class CustomRunGuiTest(unittest.TestCase): @classmethod def setUpClass(cls): @@ -387,11 +408,10 @@ def setUpClass(cls): def test_click_args(self): root = Tk() root.withdraw() - dialog = query.CommandLineArgs(root, 'Title', 'message', _utest=True) - Equal = self.assertEqual + dialog = query.CustomRun(root, 'Title', _utest=True) dialog.entry.insert(0, 'okay') dialog.button_ok.invoke() - self.assertEqual(dialog.result, ['okay']) + self.assertEqual(dialog.result, (['okay'], True)) del dialog root.destroy() del root diff --git a/Lib/idlelib/mainmenu.py b/Lib/idlelib/mainmenu.py index 6f36016296e933..5b9b603a5f5bc0 100644 --- a/Lib/idlelib/mainmenu.py +++ b/Lib/idlelib/mainmenu.py @@ -76,7 +76,7 @@ ('Python Shell', '<>'), ('C_heck Module', '<>'), ('R_un Module', '<>'), - ('Run Module with _Arguments', '<>'), + ('Run _Custom', '<>'), ]), ('shell', [ diff --git a/Lib/idlelib/query.py b/Lib/idlelib/query.py index 27e0031f8942a6..3f34eec4b45038 100644 --- a/Lib/idlelib/query.py +++ b/Lib/idlelib/query.py @@ -24,8 +24,8 @@ import shlex from sys import executable, platform # Platform is set for one test. -from tkinter import Toplevel, StringVar, W, E, S -from tkinter.ttk import Frame, Button, Entry, Label +from tkinter import Toplevel, StringVar, BooleanVar, W, E, S +from tkinter.ttk import Frame, Button, Entry, Label, Checkbutton from tkinter import filedialog from tkinter.font import Font @@ -84,7 +84,7 @@ def __init__(self, parent, title, message, *, text0='', used_names={}, self.deiconify() # Unhide now that geometry set. self.wait_window() - def create_widgets(self): # Call from override, if any. + def create_widgets(self, ok_text='OK'): # Call from override, if any. # Bind to self widgets needed for entry_ok or unittest. self.frame = frame = Frame(self, padding=10) frame.grid(column=0, row=0, sticky='news') @@ -100,7 +100,7 @@ def create_widgets(self): # Call from override, if any. self.entry_error = Label(frame, text=' ', foreground='red', font=self.error_font) self.button_ok = Button( - frame, text='OK', default='active', command=self.ok) + frame, text=ok_text, default='active', command=self.ok) self.button_cancel = Button( frame, text='Cancel', command=self.cancel) @@ -303,16 +303,36 @@ def entry_ok(self): path = self.path_ok() return None if name is None or path is None else (name, path) -class CommandLineArgs(Query): - "Get a list of parsed command line arguments." - # Used in runscript.run_module_arguments_event +class CustomRun(Query): + "Get arguments for custom run module." + # Used in runscript.run_custom_event - def __init__(self, parent, title, message, *, _htest=False, _utest=False): - super().__init__(parent, title, message, _htest=_htest, _utest=_utest) + def __init__(self, parent, title, *, cli_args='', + _htest=False, _utest=False): + """Get command line args for custom run environment. - def entry_ok(self): - "Return list of parsed arguments or None." - self.entry_error['text'] = '' + User enters the command line arugments for running the file. + """ + message = 'Command Line Arguments:' + super().__init__( + parent, title, message, text0=cli_args, + _htest=_htest, _utest=_utest) + + def create_widgets(self): + super().create_widgets(ok_text='Run') + frame = self.frame + self.restartvar = BooleanVar(self, value=True) + restart = Checkbutton(frame, variable=self.restartvar, onvalue=True, + offvalue=False, text='Restart shell') + self.args_error = Label(frame, text=' ', foreground='red', + font=self.error_font) + + restart.grid(column=0, row=4, columnspan=3, padx=5, sticky='w') + self.args_error.grid(column=0, row=12, columnspan=3, padx=5, + sticky='we') + + def cli_args_ok(self): + "Validity check and parsing for command line arguments." cli_args = self.entry.get().strip() if not cli_args: self.showerror('no arguments specified.') @@ -324,10 +344,20 @@ def entry_ok(self): return None return lex + def restart_ok(self): + return self.restartvar.get() + + def entry_ok(self): + "Return apparently valid (lex, restart) or None" + self.entry_error['text'] = '' + lex = self.cli_args_ok() + restart = self.restart_ok() + return None if not lex else (lex, restart) + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_query', verbosity=2, exit=False) from idlelib.idle_test.htest import run - run(Query, HelpSource, CommandLineArgs) + run(Query, HelpSource, CustomRun) diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py index eefacc0efd1cab..025f9b9a76a3f8 100644 --- a/Lib/idlelib/runscript.py +++ b/Lib/idlelib/runscript.py @@ -18,7 +18,7 @@ from idlelib.config import idleConf from idlelib import macosx from idlelib import pyshell -from idlelib.query import CommandLineArgs +from idlelib.query import CustomRun indent_message = """Error: Inconsistent indentation detected! @@ -114,16 +114,14 @@ def run_module_event(self, event): else: return self._run_module_event(event) - def run_module_arguments_event(self, event): - cli_args = CommandLineArgs( - event.widget, "Run with Arguments", - "Command line argunments:").result + def run_custom_event(self, event): + run_args = CustomRun(event.widget, "Customize Run").result # User cancelled. - if not cli_args: + if not run_args: return 'break' - return self._run_module_event(event, cli_args) + return self._run_module_event(event, cli_args=run_args[0], restart=run_args[1]) - def _run_module_event(self, event, cli_args=None): + def _run_module_event(self, event, *, cli_args=None, restart=True): """Run the module after setting up the environment. First check the syntax. If OK, make sure the shell is active and @@ -140,21 +138,23 @@ def _run_module_event(self, event, cli_args=None): if not self.tabnanny(filename): return 'break' interp = self.shell.interp - if pyshell.use_subprocess: + if pyshell.use_subprocess and restart: interp.restart_subprocess(with_cwd=False, filename= self.editwin._filename_to_unicode(filename)) dirname = os.path.dirname(filename) - # XXX Too often this discards arguments the user just set... argv = [filename] if cli_args: argv += cli_args + # XXX Too often this discards arguments the user just set... interp.runcommand(f"""if 1: __file__ = {filename!r} import sys as _sys from os.path import basename as _basename + argv = {argv!r} if (not _sys.argv or - _basename(_sys.argv[0]) != _basename(__file__)): - _sys.argv = {argv!r} + _basename(_sys.argv[0]) != _basename(__file__) or + len(argv) > 1): + _sys.argv = argv import os as _os _os.chdir({dirname!r}) del _sys, _basename, _os From f1e7c6111c7f64a1cf19dab6818941c65e813f8c Mon Sep 17 00:00:00 2001 From: Cheryl Sabella Date: Thu, 6 Jun 2019 17:46:37 -0400 Subject: [PATCH 05/17] Don't show warning message for new key binding --- Lib/idlelib/config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index fcde3da1d570cb..3706539da9d37e 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -591,7 +591,9 @@ def IsCoreBinding(self, virtualEvent): former_extension_events = { # Those with user-configurable keys. '<>', '<>', '<>', '<>', '<>', - '<>', '<>', '<>'} + '<>', '<>', '<>', + '<>', + } def GetCoreKeys(self, keySetName=None): """Return dict of core virtual-key keybindings for keySetName. From 03e0f590c451a52b6183c9a11c19806e7793d9f2 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sat, 15 Jun 2019 21:53:08 -0400 Subject: [PATCH 06/17] Change menu entry 'Run Custom' to 'Run ... Customized'. Revise corresponding doc entry. --- Doc/library/idle.rst | 11 ++++------- Lib/idlelib/help.html | 25 ++++++++++++++++++------- Lib/idlelib/mainmenu.py | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index 4eca68d2958cc9..bf5c971d0b14e4 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -234,13 +234,10 @@ Run Module .. _run-custom: -Run Custom - Same as :ref:`Run Module `, except allow customization of the - environment used when running the module. - - The *Command Line Arguments* are passed to the module like :data:`sys.argv` - arguments would be from the command line. This is similar to executing a - file with ``python -i file [args]``. +Run... Customized + Same as :ref:`Run Module `, but run the module with customized + settings. *Command Line Arguments* extend :data:`sys.argv` as if passed + on a command line. The module can be run in the Shell without restarting. Shell menu (Shell window only) diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 228b3195cf9253..36fb1290e3eb7e 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -6,7 +6,7 @@ - IDLE — Python 3.8.0a4 documentation + IDLE — Python 3.9.0a0 documentation @@ -19,7 +19,7 @@ @@ -50,6 +50,7 @@ +

Shell menu (Shell window only)

@@ -912,7 +923,7 @@

Navigation

  • - 3.8.0a4 Documentation » + 3.9.0a0 Documentation »
  • @@ -943,7 +954,7 @@

    Navigation



    - Last updated on May 25, 2019. + Last updated on Jun 15, 2019. Found a bug?
    diff --git a/Lib/idlelib/mainmenu.py b/Lib/idlelib/mainmenu.py index 5b9b603a5f5bc0..1b8dc475650d8d 100644 --- a/Lib/idlelib/mainmenu.py +++ b/Lib/idlelib/mainmenu.py @@ -76,7 +76,7 @@ ('Python Shell', '<>'), ('C_heck Module', '<>'), ('R_un Module', '<>'), - ('Run _Custom', '<>'), + ('Run... _Customized', '<>'), ]), ('shell', [ From 22bb3a2b2ecd23051f09b54462acb04aa52e9700 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sat, 15 Jun 2019 22:04:57 -0400 Subject: [PATCH 07/17] Expand blurb. --- Misc/NEWS.d/next/IDLE/2019-06-03-00-39-29.bpo-5680.VCQfOO.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/IDLE/2019-06-03-00-39-29.bpo-5680.VCQfOO.rst b/Misc/NEWS.d/next/IDLE/2019-06-03-00-39-29.bpo-5680.VCQfOO.rst index 199055dfd5a99f..9fc6420774888c 100644 --- a/Misc/NEWS.d/next/IDLE/2019-06-03-00-39-29.bpo-5680.VCQfOO.rst +++ b/Misc/NEWS.d/next/IDLE/2019-06-03-00-39-29.bpo-5680.VCQfOO.rst @@ -1 +1,3 @@ -Run modules from the editor using command line arguments. \ No newline at end of file +Add 'Run... Customized' to the Run menu to run a module with customized +settings. Any 'command line arguments' entered are added to sys.argv. +One can suppress the normal Shell main module restart. From 35f03799f5389b72b931bb1d473a0b58d170f80f Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sat, 15 Jun 2019 23:36:20 -0400 Subject: [PATCH 08/17] Polish run.py. --- Lib/idlelib/runscript.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py index 025f9b9a76a3f8..4ca9e5032ae23d 100644 --- a/Lib/idlelib/runscript.py +++ b/Lib/idlelib/runscript.py @@ -109,15 +109,15 @@ def run_module_event(self, event): # tries to run a module using the keyboard shortcut # (the menu item works fine). self.editwin.text_frame.after(200, - lambda: self.editwin.text_frame.event_generate('<>')) + lambda: self.editwin.text_frame.event_generate( + '<>')) return 'break' else: return self._run_module_event(event) def run_custom_event(self, event): run_args = CustomRun(event.widget, "Customize Run").result - # User cancelled. - if not run_args: + if not run_args: # User cancelled. return 'break' return self._run_module_event(event, cli_args=run_args[0], restart=run_args[1]) @@ -143,9 +143,8 @@ def _run_module_event(self, event, *, cli_args=None, restart=True): self.editwin._filename_to_unicode(filename)) dirname = os.path.dirname(filename) argv = [filename] - if cli_args: + if cli_args is not None: argv += cli_args - # XXX Too often this discards arguments the user just set... interp.runcommand(f"""if 1: __file__ = {filename!r} import sys as _sys From 09f37d7ca783a1d25ba613bf3442cfc26992d97f Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 16 Jun 2019 00:10:00 -0400 Subject: [PATCH 09/17] In runscript, pass run_args. --- Lib/idlelib/runscript.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py index 4ca9e5032ae23d..3a8576c3d7b93b 100644 --- a/Lib/idlelib/runscript.py +++ b/Lib/idlelib/runscript.py @@ -119,9 +119,9 @@ def run_custom_event(self, event): run_args = CustomRun(event.widget, "Customize Run").result if not run_args: # User cancelled. return 'break' - return self._run_module_event(event, cli_args=run_args[0], restart=run_args[1]) + return self._run_module_event(event, run_args) - def _run_module_event(self, event, *, cli_args=None, restart=True): + def _run_module_event(self, event, *, run_args=None): """Run the module after setting up the environment. First check the syntax. If OK, make sure the shell is active and @@ -137,6 +137,7 @@ def _run_module_event(self, event, *, cli_args=None, restart=True): return 'break' if not self.tabnanny(filename): return 'break' + cli_args, restart = run_args interp = self.shell.interp if pyshell.use_subprocess and restart: interp.restart_subprocess(with_cwd=False, filename= From 8d98622fb957c29d9b537f7ab3eb6e49b9515aa3 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 16 Jun 2019 00:40:51 -0400 Subject: [PATCH 10/17] More runscript edit. --- Lib/idlelib/runscript.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py index 3a8576c3d7b93b..be6882c6743a66 100644 --- a/Lib/idlelib/runscript.py +++ b/Lib/idlelib/runscript.py @@ -129,6 +129,7 @@ def _run_module_event(self, event, *, run_args=None): directory to the directory of the module being executed and also add that directory to its sys.path if not already included. """ + cli_args, restart = run_args if run_args is not None else ([], True) filename = self.getfilename() if not filename: return 'break' @@ -137,14 +138,13 @@ def _run_module_event(self, event, *, run_args=None): return 'break' if not self.tabnanny(filename): return 'break' - cli_args, restart = run_args interp = self.shell.interp if pyshell.use_subprocess and restart: interp.restart_subprocess(with_cwd=False, filename= self.editwin._filename_to_unicode(filename)) dirname = os.path.dirname(filename) argv = [filename] - if cli_args is not None: + if cli_args: argv += cli_args interp.runcommand(f"""if 1: __file__ = {filename!r} From 8c8bb4ddf820d4642f7e8a9d3e93864c544a188d Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 16 Jun 2019 01:21:02 -0400 Subject: [PATCH 11/17] Edit query and tests. --- Lib/idlelib/idle_test/test_query.py | 27 ++++++++--------------- Lib/idlelib/query.py | 33 ++++++++++++----------------- 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py index 9decedea40398c..4bed275a534442 100644 --- a/Lib/idlelib/idle_test/test_query.py +++ b/Lib/idlelib/idle_test/test_query.py @@ -257,8 +257,7 @@ def showerror(self, message): def test_blank_args(self): dialog = self.Dummy_CustomRun(' ') - self.assertEqual(dialog.cli_args_ok(), None) - self.assertIn('no arguments', dialog.entry_error['text']) + self.assertEqual(dialog.cli_args_ok(), []) def test_invalid_args(self): dialog = self.Dummy_CustomRun("'no-closing-quote") @@ -266,9 +265,9 @@ def test_invalid_args(self): self.assertIn('No closing', dialog.entry_error['text']) def test_good_args(self): - dialog = self.Dummy_CustomRun('-n 10 --verbose -p /path --name "my name"') - self.assertEqual(dialog.cli_args_ok(), - ['-n', '10', '--verbose', '-p', '/path', '--name', 'my name']) + args = ['-n', '10', '--verbose', '-p', '/path', '--name'] + dialog = self.Dummy_CustomRun(' '.join(args) + ' "my name"') + self.assertEqual(dialog.cli_args_ok(), args + ["my name"]) self.assertEqual(dialog.entry_error['text'], '') @@ -278,17 +277,17 @@ class CustomRunEntryokTest(unittest.TestCase): class Dummy_CustomRun: entry_ok = query.CustomRun.entry_ok entry_error = {} + restartvar = Var() def cli_args_ok(self): return self.cli_args - def restart_ok(self): - return self.restart def test_entry_ok_customrun(self): dialog = self.Dummy_CustomRun() - for dialog.restart in {True, False}: + for restart in {True, False}: + dialog.restartvar.set(restart) for cli_args, result in ((None, None), - ('my arg', ('my arg', dialog.restart))): - with self.subTest(): + (['my arg'], (['my arg'], restart))): + with self.subTest(restart=restart, cli_args=cli_args): dialog.cli_args = cli_args self.assertEqual(dialog.entry_ok(), result) @@ -353,9 +352,7 @@ def test_click_section_name(self): dialog.entry.insert(0, 'okay') dialog.button_ok.invoke() self.assertEqual(dialog.result, 'okay') - del dialog root.destroy() - del root class ModulenameGuiTest(unittest.TestCase): @@ -372,9 +369,7 @@ def test_click_module_name(self): self.assertEqual(dialog.entry.get(), 'idlelib') dialog.button_ok.invoke() self.assertTrue(dialog.result.endswith('__init__.py')) - del dialog root.destroy() - del root class HelpsourceGuiTest(unittest.TestCase): @@ -394,9 +389,7 @@ def test_click_help_source(self): dialog.button_ok.invoke() prefix = "file://" if sys.platform == 'darwin' else '' Equal(dialog.result, ('__test__', prefix + __file__)) - del dialog root.destroy() - del root class CustomRunGuiTest(unittest.TestCase): @@ -412,9 +405,7 @@ def test_click_args(self): dialog.entry.insert(0, 'okay') dialog.button_ok.invoke() self.assertEqual(dialog.result, (['okay'], True)) - del dialog root.destroy() - del root if __name__ == '__main__': diff --git a/Lib/idlelib/query.py b/Lib/idlelib/query.py index 3f34eec4b45038..9b3bb1d186b89c 100644 --- a/Lib/idlelib/query.py +++ b/Lib/idlelib/query.py @@ -304,16 +304,17 @@ def entry_ok(self): return None if name is None or path is None else (name, path) class CustomRun(Query): - "Get arguments for custom run module." + """Get settings for custom run of module. + + 1. Command line arguments to extend sys.argv. + 2. Whether to restart Shell or not. + """ # Used in runscript.run_custom_event def __init__(self, parent, title, *, cli_args='', _htest=False, _utest=False): - """Get command line args for custom run environment. - - User enters the command line arugments for running the file. - """ - message = 'Command Line Arguments:' + # TODO Use cli_args to pre-populate entry. + message = 'Command Line Arguments for sys.argv:' super().__init__( parent, title, message, text0=cli_args, _htest=_htest, _utest=_utest) @@ -333,26 +334,20 @@ def create_widgets(self): def cli_args_ok(self): "Validity check and parsing for command line arguments." - cli_args = self.entry.get().strip() - if not cli_args: - self.showerror('no arguments specified.') - return None + cli_string = self.entry.get().strip() try: - lex = shlex.split(cli_args, posix=True) + cli_args = shlex.split(cli_string, posix=True) except ValueError as err: self.showerror(str(err)) return None - return lex - - def restart_ok(self): - return self.restartvar.get() + return cli_args def entry_ok(self): - "Return apparently valid (lex, restart) or None" + "Return apparently valid (cli_args, restart) or None" self.entry_error['text'] = '' - lex = self.cli_args_ok() - restart = self.restart_ok() - return None if not lex else (lex, restart) + cli_args = self.cli_args_ok() + restart = self.restartvar.get() + return None if cli_args is None else (cli_args, restart) if __name__ == '__main__': From 845178b24c3042ba959866c6b75b6b7f6655d809 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 16 Jun 2019 01:59:54 -0400 Subject: [PATCH 12/17] Move some test dummy attributes to instance. --- Lib/idlelib/idle_test/test_query.py | 31 ++++++++++++----------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py index 4bed275a534442..00dd5f4bf59bc4 100644 --- a/Lib/idlelib/idle_test/test_query.py +++ b/Lib/idlelib/idle_test/test_query.py @@ -83,7 +83,7 @@ class Dummy_SectionName: entry = Var() entry_error = {} def __init__(self, dummy_entry): - self.entry.set(dummy_entry) + self.entry = Var(value=dummy_entry) self.entry_error['text'] = '' def showerror(self, message): self.entry_error['text'] = message @@ -115,11 +115,9 @@ class ModuleNameTest(unittest.TestCase): class Dummy_ModuleName: entry_ok = query.ModuleName.entry_ok # Function being tested. text0 = '' - entry = Var() - entry_error = {} def __init__(self, dummy_entry): - self.entry.set(dummy_entry) - self.entry_error['text'] = '' + self.entry = Var(value=dummy_entry) + self.entry_error = {'text': ''} def showerror(self, message): self.entry_error['text'] = message @@ -144,9 +142,7 @@ def test_good_module_name(self): self.assertEqual(dialog.entry_error['text'], '') -# 3 HelpSource test classes each test one function. - -orig_platform = query.platform +# 3 HelpSource test classes each test one method. class HelpsourceBrowsefileTest(unittest.TestCase): "Test browse_file method of ModuleName subclass of Query." @@ -178,17 +174,16 @@ class HelpsourcePathokTest(unittest.TestCase): class Dummy_HelpSource: path_ok = query.HelpSource.path_ok - path = Var() - path_error = {} def __init__(self, dummy_path): - self.path.set(dummy_path) - self.path_error['text'] = '' + self.path = Var(value=dummy_path) + self.path_error = {'text': ''} def showerror(self, message, widget=None): self.path_error['text'] = message + orig_platform = query.platform # Set in test_path_ok_file. @classmethod def tearDownClass(cls): - query.platform = orig_platform + query.platform = cls.orig_platform def test_path_ok_blank(self): dialog = self.Dummy_HelpSource(' ') @@ -242,16 +237,16 @@ def test_entry_ok_helpsource(self): self.assertEqual(dialog.entry_ok(), result) +# 2 CustomRun test classes each test one method. + class CustomRunCLIargsokTest(unittest.TestCase): "Test cli_ok method of the CustomRun subclass of Query." class Dummy_CustomRun: - cli_args_ok = query.CustomRun.cli_args_ok # Function being tested. - entry = Var() - entry_error = {} + cli_args_ok = query.CustomRun.cli_args_ok def __init__(self, dummy_entry): - self.entry.set(dummy_entry) - self.entry_error['text'] = '' + self.entry = Var(value=dummy_entry) + self.entry_error = {'text': ''} def showerror(self, message): self.entry_error['text'] = message From 31416fd3d8124eba8311368c2d0a0f0da4abe502 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 16 Jun 2019 02:09:51 -0400 Subject: [PATCH 13/17] A couple more. --- Lib/idlelib/idle_test/test_query.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py index 00dd5f4bf59bc4..149ff3febdddfe 100644 --- a/Lib/idlelib/idle_test/test_query.py +++ b/Lib/idlelib/idle_test/test_query.py @@ -30,11 +30,9 @@ class Dummy_Query: ok = query.Query.ok cancel = query.Query.cancel # Add attributes and initialization needed for tests. - entry = Var() - entry_error = {} def __init__(self, dummy_entry): - self.entry.set(dummy_entry) - self.entry_error['text'] = '' + self.entry = Var(value=dummy_entry) + self.entry_error = {'text': ''} self.result = None self.destroyed = False def showerror(self, message): @@ -80,11 +78,9 @@ class SectionNameTest(unittest.TestCase): class Dummy_SectionName: entry_ok = query.SectionName.entry_ok # Function being tested. used_names = ['used'] - entry = Var() - entry_error = {} def __init__(self, dummy_entry): self.entry = Var(value=dummy_entry) - self.entry_error['text'] = '' + self.entry_error = {'text': ''} def showerror(self, message): self.entry_error['text'] = message From fbfca230f7dada240fa3d3e53e31a002b587e0f5 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 16 Jun 2019 02:11:20 -0400 Subject: [PATCH 14/17] Update query coverage. --- Lib/idlelib/idle_test/test_query.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py index 149ff3febdddfe..3b444de15d7c0f 100644 --- a/Lib/idlelib/idle_test/test_query.py +++ b/Lib/idlelib/idle_test/test_query.py @@ -1,4 +1,4 @@ -"""Test query, coverage 91%). +"""Test query, coverage 93%). Non-gui tests for Query, SectionName, ModuleName, and HelpSource use dummy versions that extract the non-gui methods and add other needed From 4da67c35a1889cdedc29f56d6d9d82d341e5902f Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 16 Jun 2019 04:32:30 -0400 Subject: [PATCH 15/17] pass rub_args by keyword --- Lib/idlelib/runscript.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py index be6882c6743a66..27dc20613b52e5 100644 --- a/Lib/idlelib/runscript.py +++ b/Lib/idlelib/runscript.py @@ -119,7 +119,7 @@ def run_custom_event(self, event): run_args = CustomRun(event.widget, "Customize Run").result if not run_args: # User cancelled. return 'break' - return self._run_module_event(event, run_args) + return self._run_module_event(event, run_args=run_args) def _run_module_event(self, event, *, run_args=None): """Run the module after setting up the environment. From 4a64274f0c5f06df12ee237c6312241e8b15091e Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Mon, 17 Jun 2019 21:10:34 -0400 Subject: [PATCH 16/17] Show customize box after check, attach to shell. Don't ask for config if still may toss. Want focus to go to shell unless cancel. --- Lib/idlelib/runscript.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py index 27dc20613b52e5..5d49cfda6a1f3e 100644 --- a/Lib/idlelib/runscript.py +++ b/Lib/idlelib/runscript.py @@ -116,12 +116,9 @@ def run_module_event(self, event): return self._run_module_event(event) def run_custom_event(self, event): - run_args = CustomRun(event.widget, "Customize Run").result - if not run_args: # User cancelled. - return 'break' - return self._run_module_event(event, run_args=run_args) + return self._run_module_event(event, customize=True) - def _run_module_event(self, event, *, run_args=None): + def _run_module_event(self, event, *, customize=False): """Run the module after setting up the environment. First check the syntax. If OK, make sure the shell is active and @@ -129,7 +126,6 @@ def _run_module_event(self, event, *, run_args=None): directory to the directory of the module being executed and also add that directory to its sys.path if not already included. """ - cli_args, restart = run_args if run_args is not None else ([], True) filename = self.getfilename() if not filename: return 'break' @@ -139,6 +135,12 @@ def _run_module_event(self, event, *, run_args=None): if not self.tabnanny(filename): return 'break' interp = self.shell.interp + if customize: + title = f"Customize {self.editwin.short_title()} Run" + run_args = CustomRun(self.shell.text, title).result + if not run_args: # User cancelled. + return 'break' + cli_args, restart = run_args if customize else ([], True) if pyshell.use_subprocess and restart: interp.restart_subprocess(with_cwd=False, filename= self.editwin._filename_to_unicode(filename)) From 18177da05d8ca896cc75ea30c8cb1f8e9da0166a Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Mon, 17 Jun 2019 21:38:21 -0400 Subject: [PATCH 17/17] Minor tweaks. --- Lib/idlelib/runscript.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py index 5d49cfda6a1f3e..b041e56fb840e1 100644 --- a/Lib/idlelib/runscript.py +++ b/Lib/idlelib/runscript.py @@ -121,10 +121,11 @@ def run_custom_event(self, event): def _run_module_event(self, event, *, customize=False): """Run the module after setting up the environment. - First check the syntax. If OK, make sure the shell is active and - then transfer the arguments, set the run environment's working - directory to the directory of the module being executed and also - add that directory to its sys.path if not already included. + First check the syntax. Next get customization. If OK, make + sure the shell is active and then transfer the arguments, set + the run environment's working directory to the directory of the + module being executed and also add that directory to its + sys.path if not already included. """ filename = self.getfilename() if not filename: @@ -134,16 +135,17 @@ def _run_module_event(self, event, *, customize=False): return 'break' if not self.tabnanny(filename): return 'break' - interp = self.shell.interp if customize: title = f"Customize {self.editwin.short_title()} Run" run_args = CustomRun(self.shell.text, title).result if not run_args: # User cancelled. return 'break' cli_args, restart = run_args if customize else ([], True) + interp = self.shell.interp if pyshell.use_subprocess and restart: - interp.restart_subprocess(with_cwd=False, filename= - self.editwin._filename_to_unicode(filename)) + interp.restart_subprocess( + with_cwd=False, filename= + self.editwin._filename_to_unicode(filename)) dirname = os.path.dirname(filename) argv = [filename] if cli_args: