Skip to content

Commit 26743a7

Browse files
authored
Merge pull request #162 from python-cmd2/py_tests
Fixed a major bug in the pyscript command on Windows
2 parents 79d5b67 + 4e8c08e commit 26743a7

5 files changed

Lines changed: 67 additions & 8 deletions

File tree

CHANGES.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ News
44
0.7.4
55
-----
66

7-
*Release date: TBD*
7+
*Release date: 2017-07-TBD*
88

99
* Bug fixes
1010
* Fixed a couple bugs in interacting with pastebuffer/clipboard on macOS and Linux
1111
* Fixed a couple bugs in edit and save commands if called when history is empty
1212
* Ability to pipe ``cmd2`` command output to a shell command is now more reliable, particularly on Windows
13+
* Fixed a bug in ``pyscript`` command on Windows related to ``\`` being interpreted as an escape
1314
* Enhancements
1415
* Ensure that path and shell command tab-completion results are alphabetically sorted
1516
* Removed feature for load command to load scripts from URLS
@@ -18,8 +19,10 @@ News
1819
* These also strongly felt out of place
1920
* ``load`` and ``_relative_load`` now require a file path
2021
* ``edit`` and ``save`` now use a temporary file if a file path isn't provided
21-
* Load command has better error checking and reporting
22-
* Clipboard copy and paste functionality is now handled by the ``pyperclip`` module
22+
* ``load`` command has better error checking and reporting
23+
* Clipboard copy and paste functionality is now handled by the **pyperclip** module
24+
* NOTE: This adds an additional required 3rd-party dependency
25+
* Added a lot of unit tests
2326

2427
0.7.3
2528
-----

cmd2.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,7 +1421,7 @@ def do_pyscript(self, arg, opts=None):
14211421
arg = shlex.split(arg, posix=POSIX_SHLEX)
14221422

14231423
# Get the absolute path of the script
1424-
script_path = os.path.abspath(os.path.expanduser(arg[0]))
1424+
script_path = os.path.expanduser(arg[0])
14251425

14261426
# Save current command line arguments
14271427
orig_args = sys.argv
@@ -1430,8 +1430,8 @@ def do_pyscript(self, arg, opts=None):
14301430
sys.argv = [script_path]
14311431
sys.argv.extend(arg[1:])
14321432

1433-
# Run the script
1434-
self.do_py("run('{}')".format(script_path))
1433+
# Run the script - use repr formatting to escape things which need to be escaped to prevent issues on Windows
1434+
self.do_py("run({!r})".format(script_path))
14351435

14361436
# Restore command line arguments to original state
14371437
sys.argv = orig_args

tests/scripts/raises_exception.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env python
2+
# coding=utf-8
3+
"""
4+
Example demonstrating what happens when a Python script raises an exception
5+
"""
6+
1 + 'blue'

tests/scripts/recursive.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env python
2+
# coding=utf-8
3+
"""
4+
Example demonstrating that running a Python script recursively inside another Python script isn't allowed
5+
"""
6+
cmd('pyscript ../script.py')

tests/test_cmd2.py

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,6 @@ def test_base_run_python_script(base_app, capsys, request):
131131
assert out == expected
132132

133133

134-
@pytest.mark.skipif(sys.platform == 'win32',
135-
reason="Unit test doesn't work on win32, but feature does")
136134
def test_base_run_pyscript(base_app, capsys, request):
137135
test_dir = os.path.dirname(request.module.__file__)
138136
python_script = os.path.join(test_dir, 'script.py')
@@ -142,6 +140,34 @@ def test_base_run_pyscript(base_app, capsys, request):
142140
out, err = capsys.readouterr()
143141
assert out == expected
144142

143+
def test_recursive_pyscript_not_allowed(base_app, capsys, request):
144+
test_dir = os.path.dirname(request.module.__file__)
145+
python_script = os.path.join(test_dir, 'scripts', 'recursive.py')
146+
expected = 'ERROR: Recursively entering interactive Python consoles is not allowed.\n'
147+
148+
run_cmd(base_app, "pyscript {}".format(python_script))
149+
out, err = capsys.readouterr()
150+
assert err == expected
151+
152+
def test_pyscript_with_nonexist_file(base_app, capsys):
153+
python_script = 'does_not_exist.py'
154+
run_cmd(base_app, "pyscript {}".format(python_script))
155+
out, err = capsys.readouterr()
156+
assert err.startswith('ERROR: [Errno 2] No such file or directory:')
157+
158+
def test_pyscript_with_exception(base_app, capsys, request):
159+
test_dir = os.path.dirname(request.module.__file__)
160+
python_script = os.path.join(test_dir, 'scripts', 'raises_exception.py')
161+
run_cmd(base_app, "pyscript {}".format(python_script))
162+
out, err = capsys.readouterr()
163+
assert err.startswith('Traceback')
164+
assert err.endswith("TypeError: unsupported operand type(s) for +: 'int' and 'str'\n")
165+
166+
def test_pyscript_requires_an_argument(base_app, capsys):
167+
run_cmd(base_app, "pyscript")
168+
out, err = capsys.readouterr()
169+
assert err.startswith('ERROR: pyscript command requires at least 1 argument ...')
170+
145171

146172
def test_base_error(base_app):
147173
out = run_cmd(base_app, 'meow')
@@ -957,3 +983,21 @@ def test_select_uneven_list_of_tuples(select_app):
957983

958984
# And verify the expected output to stdout
959985
assert out == expected
986+
987+
@pytest.fixture
988+
def noarglist_app():
989+
cmd2.set_use_arg_list(False)
990+
app = cmd2.Cmd()
991+
app.stdout = StdOut()
992+
return app
993+
994+
def test_pyscript_with_noarglist(noarglist_app, capsys, request):
995+
test_dir = os.path.dirname(request.module.__file__)
996+
python_script = os.path.join(test_dir, '..', 'examples', 'scripts', 'arg_printer.py')
997+
expected = """Running Python script 'arg_printer.py' which was called with 2 arguments
998+
arg 1: 'foo'
999+
arg 2: 'bar'
1000+
"""
1001+
run_cmd(noarglist_app, 'pyscript {} foo bar'.format(python_script))
1002+
out, err = capsys.readouterr()
1003+
assert out == expected

0 commit comments

Comments
 (0)