Skip to content

Commit 1a26c02

Browse files
committed
Merge branch 'master' into ansi_to_style
2 parents 801bab8 + 6a1ec96 commit 1a26c02

File tree

5 files changed

+49
-64
lines changed

5 files changed

+49
-64
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.9.23 (TBD, 2019)
2+
* Bug Fixes
3+
* Fixed bug where startup script containing a single quote in its file name was incorrectly quoted
4+
15
## 0.9.22 (December 9, 2019)
26
* Bug Fixes
37
* Fixed bug where a redefined `ansi.style_error` was not being used in all `cmd2` files

cmd2/cmd2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
300300
if startup_script:
301301
startup_script = os.path.abspath(os.path.expanduser(startup_script))
302302
if os.path.exists(startup_script):
303-
self._startup_commands.append("run_script '{}'".format(startup_script))
303+
self._startup_commands.append("run_script {}".format(utils.quote_string(startup_script)))
304304

305305
# Transcript files to run instead of interactive command loop
306306
self._transcript_files = None

tests/conftest.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,15 @@ def base_app():
157157
return cmd2.Cmd()
158158

159159

160+
# These are odd file names for testing quoting of them
161+
odd_file_names = [
162+
'nothingweird',
163+
'has spaces',
164+
'"is_double_quoted"',
165+
"'is_single_quoted'"
166+
]
167+
168+
160169
def complete_tester(text: str, line: str, begidx: int, endidx: int, app) -> Optional[str]:
161170
"""
162171
This is a convenience function to test cmd2.complete() since

tests/test_cmd2.py

Lines changed: 26 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
import cmd2
2323
from cmd2 import ansi, clipboard, constants, plugin, utils, COMMAND_NAME
24-
from .conftest import run_cmd, normalize, verify_help_text, HELP_HISTORY
25-
from .conftest import SHORTCUTS_TXT, SHOW_TXT, SHOW_LONG, complete_tester
24+
from .conftest import (run_cmd, normalize, verify_help_text, HELP_HISTORY, SHORTCUTS_TXT, SHOW_TXT,
25+
SHOW_LONG, complete_tester, odd_file_names)
2626

2727
def CreateOutsimApp():
2828
c = cmd2.Cmd()
@@ -431,31 +431,15 @@ def test_relative_run_script(base_app, request):
431431
assert script_out == manual_out
432432
assert script_err == manual_err
433433

434-
def test_relative_run_script_with_odd_file_names(base_app, monkeypatch):
434+
@pytest.mark.parametrize('file_name', odd_file_names)
435+
def test_relative_run_script_with_odd_file_names(base_app, file_name, monkeypatch):
435436
"""Test file names with various patterns"""
436437
# Mock out the do_run_script call to see what args are passed to it
437438
run_script_mock = mock.MagicMock(name='do_run_script')
438439
monkeypatch.setattr("cmd2.Cmd.do_run_script", run_script_mock)
439440

440-
file_name = utils.quote_string('nothingweird.txt')
441-
out, err = run_cmd(base_app, "_relative_run_script {}".format(file_name))
442-
run_script_mock.assert_called_once_with('"nothingweird.txt"')
443-
run_script_mock.reset_mock()
444-
445-
file_name = utils.quote_string('has spaces.txt')
446-
out, err = run_cmd(base_app, "_relative_run_script {}".format(file_name))
447-
run_script_mock.assert_called_once_with('"has spaces.txt"')
448-
run_script_mock.reset_mock()
449-
450-
file_name = utils.quote_string('"is_double_quoted.txt"')
451-
out, err = run_cmd(base_app, "_relative_run_script {}".format(file_name))
452-
run_script_mock.assert_called_once_with('\'"is_double_quoted.txt"\'')
453-
run_script_mock.reset_mock()
454-
455-
file_name = utils.quote_string("'is_single_quoted.txt'")
456-
out, err = run_cmd(base_app, "_relative_run_script {}".format(file_name))
457-
run_script_mock.assert_called_once_with('"\'is_single_quoted.txt\'"')
458-
run_script_mock.reset_mock()
441+
run_cmd(base_app, "_relative_run_script {}".format(utils.quote_string(file_name)))
442+
run_script_mock.assert_called_once_with(utils.quote_string(file_name))
459443

460444
def test_relative_run_script_requires_an_argument(base_app):
461445
out, err = run_cmd(base_app, '_relative_run_script')
@@ -715,35 +699,17 @@ def test_edit_file(base_app, request, monkeypatch):
715699
# We think we have an editor, so should expect a Popen call
716700
m.assert_called_once()
717701

718-
def test_edit_file_with_odd_file_names(base_app, monkeypatch):
702+
@pytest.mark.parametrize('file_name', odd_file_names)
703+
def test_edit_file_with_odd_file_names(base_app, file_name, monkeypatch):
719704
"""Test editor and file names with various patterns"""
720705
# Mock out the do_shell call to see what args are passed to it
721706
shell_mock = mock.MagicMock(name='do_shell')
722707
monkeypatch.setattr("cmd2.Cmd.do_shell", shell_mock)
723708

724709
base_app.editor = 'fooedit'
725710
file_name = utils.quote_string('nothingweird.py')
726-
out, err = run_cmd(base_app, "edit {}".format(file_name))
727-
shell_mock.assert_called_once_with('"fooedit" "nothingweird.py"')
728-
shell_mock.reset_mock()
729-
730-
base_app.editor = 'foo edit'
731-
file_name = utils.quote_string('has spaces.py')
732-
out, err = run_cmd(base_app, "edit {}".format(file_name))
733-
shell_mock.assert_called_once_with('"foo edit" "has spaces.py"')
734-
shell_mock.reset_mock()
735-
736-
base_app.editor = '"fooedit"'
737-
file_name = utils.quote_string('"is_double_quoted.py"')
738-
out, err = run_cmd(base_app, "edit {}".format(file_name))
739-
shell_mock.assert_called_once_with('\'"fooedit"\' \'"is_double_quoted.py"\'')
740-
shell_mock.reset_mock()
741-
742-
base_app.editor = "'fooedit'"
743-
file_name = utils.quote_string("'is_single_quoted.py'")
744-
out, err = run_cmd(base_app, "edit {}".format(file_name))
745-
shell_mock.assert_called_once_with('"\'fooedit\'" "\'is_single_quoted.py\'"')
746-
shell_mock.reset_mock()
711+
run_cmd(base_app, "edit {}".format(utils.quote_string(file_name)))
712+
shell_mock.assert_called_once_with('"fooedit" {}'.format(utils.quote_string(file_name)))
747713

748714
def test_edit_file_with_spaces(base_app, request, monkeypatch):
749715
# Set a fake editor just to make sure we have one. We aren't really going to call it due to the mock
@@ -2386,14 +2352,29 @@ def test_startup_script(request):
23862352
startup_script = os.path.join(test_dir, '.cmd2rc')
23872353
app = cmd2.Cmd(allow_cli_args=False, startup_script=startup_script)
23882354
assert len(app._startup_commands) == 1
2389-
assert app._startup_commands[0] == "run_script '{}'".format(startup_script)
2355+
assert app._startup_commands[0] == "run_script {}".format(utils.quote_string(startup_script))
23902356
app._startup_commands.append('quit')
23912357
app.cmdloop()
23922358
out, err = run_cmd(app, 'alias list')
23932359
assert len(out) > 1
23942360
assert 'alias create ls' in out[0]
23952361

23962362

2363+
@pytest.mark.parametrize('startup_script', odd_file_names)
2364+
def test_startup_script_with_odd_file_names(startup_script):
2365+
"""Test file names with various patterns"""
2366+
# Mock os.path.exists to trick cmd2 into adding this script to its startup commands
2367+
saved_exists = os.path.exists
2368+
os.path.exists = mock.MagicMock(name='exists', return_value=True)
2369+
2370+
app = cmd2.Cmd(allow_cli_args=False, startup_script=startup_script)
2371+
assert len(app._startup_commands) == 1
2372+
assert app._startup_commands[0] == "run_script {}".format(utils.quote_string(os.path.abspath(startup_script)))
2373+
2374+
# Restore os.path.exists
2375+
os.path.exists = saved_exists
2376+
2377+
23972378
def test_transcripts_at_init():
23982379
transcript_files = ['foo', 'bar']
23992380
app = cmd2.Cmd(allow_cli_args=False, transcript_files=transcript_files)

tests/test_run_pyscript.py

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import builtins
77
import os
88

9+
import pytest
10+
911
from cmd2 import plugin, utils
10-
from .conftest import run_cmd
12+
from .conftest import run_cmd, odd_file_names
1113

1214
# Python 3.5 had some regressions in the unitest.mock module, so use 3rd party mock if available
1315
try:
@@ -52,30 +54,19 @@ def test_run_pyscript_with_non_python_file(base_app, request):
5254
out, err = run_cmd(base_app, 'run_pyscript {}'.format(filename))
5355
assert "does not have a .py extension" in err[0]
5456

55-
def test_run_pyscript_with_odd_file_names(base_app):
57+
@pytest.mark.parametrize('python_script', odd_file_names)
58+
def test_run_pyscript_with_odd_file_names(base_app, python_script):
5659
"""
5760
Pass in file names with various patterns. Since these files don't exist, we will rely
5861
on the error text to make sure the file names were processed correctly.
5962
"""
60-
python_script = utils.quote_string('nothingweird.py')
61-
out, err = run_cmd(base_app, "run_pyscript {}".format(python_script))
62-
assert "Error reading script file 'nothingweird.py'" in err[0]
63-
64-
python_script = utils.quote_string('has spaces.py')
65-
out, err = run_cmd(base_app, "run_pyscript {}".format(python_script))
66-
assert "Error reading script file 'has spaces.py'" in err[0]
67-
68-
# For remaining tests, mock input to get us passed the warning about not ending in .py
63+
# Mock input to get us passed the warning about not ending in .py
6964
input_mock = mock.MagicMock(name='input', return_value='1')
7065
builtins.input = input_mock
7166

72-
python_script = utils.quote_string('"is_double_quoted.py"')
73-
out, err = run_cmd(base_app, "run_pyscript {}".format(python_script))
74-
assert "Error reading script file '\"is_double_quoted.py\"'" in err[1]
75-
76-
python_script = utils.quote_string("'is_single_quoted.py'")
77-
out, err = run_cmd(base_app, "run_pyscript {}".format(python_script))
78-
assert "Error reading script file ''is_single_quoted.py''" in err[1]
67+
out, err = run_cmd(base_app, "run_pyscript {}".format(utils.quote_string(python_script)))
68+
err = ''.join(err)
69+
assert "Error reading script file '{}'".format(python_script) in err
7970

8071
def test_run_pyscript_with_exception(base_app, request):
8172
test_dir = os.path.dirname(request.module.__file__)

0 commit comments

Comments
 (0)