Repository: python-cmd2/cmd2

Issue:
Add ability to pass arguments to a Python script
The **py** command supports running a Python script via "py run('script.py')".  However, it does not currently support the ability to pass any arguments to the script.

This functionality would be a lot more flexible and reusable if arguments could be passed to the script.

So either either enhance the current py command with the ability to run a script with arguments or add a new command which supports the ability to run a script and pass it arguments.

Discussion:

Patch:
diff --git a/CHANGES.md b/CHANGES.md
index 2324522f..c1686888 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -11,6 +11,7 @@ News
 * Enhancements
     * Added the ability to exclude commands from the help menu (**eof** included by default)
     * Redundant list command removed and features merged into history command
+    * Added **pyscript** command which supports running Python scripts with arguments
 
 0.7.2
 -----
diff --git a/README.md b/README.md
index cd739773..8c5141b6 100755
--- a/README.md
+++ b/README.md
@@ -155,8 +155,9 @@ example/exampleSession.txt:
 
 Documented commands (type help <topic>):
 ========================================
-_relative_load  edit  help     list  orate  py    run   say  shell      show
-cmdenvironment  eof   history  load  pause  quit  save  set  shortcuts  speak
+_relative_load  help     orate  pyscript  save  shell      speak
+cmdenvironment  history  pause  quit      say   shortcuts
+edit            load     py     run       set   show
 
 (Cmd) help say
 Repeats what you tell me to.
diff --git a/cmd2.py b/cmd2.py
index 3fe13f54..aabda96e 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -1583,6 +1583,42 @@ class Cmd(cmd.Cmd):
             self._in_py = False
         return self._should_quit
 
+    # noinspection PyUnusedLocal
+    @options([], arg_desc='<script_path> [script_arguments]')
+    def do_pyscript(self, arg, opts=None):
+        """\nRuns a python script file inside the console
+
+Console commands can be executed inside this script with cmd("your command")
+However, you cannot run nested "py" or "pyscript" commands from within this script
+Paths or arguments that contain spaces must be enclosed in quotes
+"""
+        if not arg:
+            self.perror("pyscript command requires at least 1 argument ...", traceback_war=False)
+            self.do_help('pyscript')
+            return
+
+        if not USE_ARG_LIST:
+            arg = shlex.split(arg, posix=POSIX_SHLEX)
+
+        # Get the absolute path of the script
+        script_path = os.path.abspath(os.path.expanduser(arg[0]))
+
+        # Save current command line arguments
+        orig_args = sys.argv
+
+        # Overwrite sys.argv to allow the script to take command line arguments
+        sys.argv = [script_path]
+        sys.argv.extend(arg[1:])
+
+        # Run the script
+        self.do_py("run('{}')".format(arg[0]))
+
+        # Restore command line arguments to original state
+        sys.argv = orig_args
+
+    # Enable tab completion of paths for pyscript command
+    complete_pyscript = path_complete
+
     # Only include the do_ipy() method if IPython is available on the system
     if ipython_available:
         # noinspection PyMethodMayBeStatic,PyUnusedLocal
diff --git a/examples/arg_printer.py b/examples/arg_printer.py
new file mode 100755
index 00000000..42084d4e
--- /dev/null
+++ b/examples/arg_printer.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+# coding=utf-8
+import sys
+print("Running Python script {!r} which was called with {} arguments".format(sys.argv[0], len(sys.argv) - 1))
+for i, arg in enumerate(sys.argv[1:]):
+    print("arg {}: {!r}".format(i+1, arg))
diff --git a/examples/exampleSession.txt b/examples/exampleSession.txt
index 62c130f0..b2cf24c0 100644
--- a/examples/exampleSession.txt
+++ b/examples/exampleSession.txt
@@ -3,8 +3,9 @@
 
 Documented commands (type help <topic>):
 ========================================
-_relative_load  edit  history  orate  py    run   say  shell      show
-cmdenvironment  help  load     pause  quit  save  set  shortcuts  speak
+_relative_load  help     orate  pyscript  save  shell      speak
+cmdenvironment  history  pause  quit      say   shortcuts
+edit            load     py     run       set   show
 
 (Cmd) help say
 Repeats what you tell me to.


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
index 41bd007a..77f525f7 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -15,8 +15,8 @@ import cmd2
 # Help text for base cmd2.Cmd application
 BASE_HELP = """Documented commands (type help <topic>):
 ========================================
-_relative_load  edit  history  pause  quit  save  shell      show
-cmdenvironment  help  load     py     run   set   shortcuts
+_relative_load  edit  history  pause  pyscript  run   set    shortcuts
+cmdenvironment  help  load     py     quit      save  shell  show
 """
 
 # Help text for the history command
diff --git a/tests/test_transcript.py b/tests/test_transcript.py
index b193a20d..5ac7d6fd 100644
--- a/tests/test_transcript.py
+++ b/tests/test_transcript.py
@@ -106,8 +106,9 @@ def test_base_with_transcript(_cmdline_app):
 
 Documented commands (type help <topic>):
 ========================================
-_relative_load  edit  history  orate  py    run   say  shell      show
-cmdenvironment  help  load     pause  quit  save  set  shortcuts  speak
+_relative_load  help     orate  pyscript  save  shell      speak
+cmdenvironment  history  pause  quit      say   shortcuts
+edit            load     py     run       set   show
 
 (Cmd) help say
 Repeats what you tell me to.
diff --git a/tests/transcript.txt b/tests/transcript.txt
index d0fd86a6..582f08cb 100644
--- a/tests/transcript.txt
+++ b/tests/transcript.txt
@@ -2,8 +2,9 @@
 
 Documented commands (type help <topic>):
 ========================================
-_relative_load  edit  history  orate  py    run   say  shell      show
-cmdenvironment  help  load     pause  quit  save  set  shortcuts  speak
+_relative_load  help     orate  pyscript  save  shell      speak
+cmdenvironment  history  pause  quit      say   shortcuts
+edit            load     py     run       set   show
 
 (Cmd) help say
 Repeats what you tell me to.